How to use React Navigation with an element inside of a FlatList's Header? - react-native

I can navigate perfectly within the renderItem, but when i try within the component that I use in the header when I click it says "undefinded is not an object (evaluating '_this.props.navigation.navigate')
This is how Im trying to navigate within the component thats been passed to the FlatLists's header
<TouchableOpacity onPress={() => this.props.navigation.navigate('Profile', { data: info })}>

I passed through the navigation prop to the ListHeaderComponent, and it works, because the rendered element gave me some other problems
This is how i did it
return(
<SafeAreaView style={styles.container}>
<FlatList
ListHeaderComponent={
<>
<Header navigation={this.props.navigation}/>
</>
}
style={styles.scrollView}
numColumns='2'
columnWrapperStyle={{justifyContent: 'space-between'}}
data={ex}
renderItem={renderItem}
keyExtractor={(item, index) => index.toString()}
/>
</SafeAreaView>
);

Just a hunch, but my guess is the component is being passed for ListHeaderComponent instead of a rendered element with the navigation prop.
For example:
function Parent(props) {
// Here the FlatList will render the header as <MyHeader /> with no props
// If this.props.navigation is called in MyHeader it will be undefined
return (
<FlatList ListHeaderComponent={MyHeader} ... />
);
}
vs
function Parent(props) {
// here MyHeader is rendered as an element first, passing through
// the necessary navigation prop
const headerElement = (<MyHeader navigation={props.navigation} />);
return (
<FlatList ListHeaderComponent={headerElement} ... />
);
}

Related

React Native - VirtualizedLists should never be nested inside plain ScrollViews with the same orientation

I'm working on an app for existing web application with expo cli.
I have completed the home screen but I'm getting this warning when using ScrollView
VirtualizedLists should never be nested inside plain ScrollViews with
the same orientation - use another VirtualizedList-backed container
instead.
I have a folder screens where I've all the pages of the website. so currently I have Home.js where I have different sections.
<View>
<Showcase />
<StepsList />
<HomeInfo />
<HomeCorporateMenu />
<HomeMonthlyMenus />
</View>
Then rendeing this component in the root component App.js. but I was not able to scroll down to see other sections.
So I've added SafeAreaView and ScrollView components. now I'm able to scroll but sometimes I get that warning in the console.
I have looked it up SO and found some solutions.
Added style={{ flex: 1 }} and keyboardShouldPersistTaps='always' to ScrollView component
But Still getting the same warning. Any suggestions?
<SafeAreaView style={styles.container}>
<ScrollView>
<Header />
<HomeScreen />
</ScrollView>
</SafeAreaView>
The warning is, obviously, telling you that you shouldn't nest multiple VirtualizedList (FlatList and SectionList) components with the same orientation (the orientation of your lists is probably vertical).
To do it properly, and for the warning to disappear, you have to use the ListHeaderComponent or ListFooterComponent prop of the VirtualizedList and nest them like this:
const App = () => {
const ListFooterComponent = (
<>
<FlatList
// other FlatList props
data={stepsListData}
/>
<FlatList
// other FlatList props
data={homeInfoData}
/>
<FlatList
// other FlatList props
data={homeCorporateMenuData}
/>
{/* ... */}
</>
);
return (
<FlatList
// other FlatList props
data={showcaseData}
ListFooterComponent={ListFooterComponent}
/>
);
};
Or another possible workaround (and not an official resolution) would be to use a FlatList with empty data and renderItem props instead of using a ScrollView. Instead of this:
const App = () => {
return (
<SafeAreaView style={styles.container}>
<ScrollView>
<Header />
<HomeScreen />
</ScrollView>
</SafeAreaView>
);
};
You can use this:
const emptyData = [];
const renderNullItem = () => null;
const App = () => {
const ListFooterComponent = (
<>
<Header />
<HomeScreen />
</>
);
return (
<SafeAreaView style={styles.container}>
<FlatList
data={emptyData}
renderItem={renderNullItem}
ListFooterComponent={ListFooterComponent}
/>
</SafeAreaView>
);
};

React native Flatlist TouchableOpacity OnPress Not Working On Android

Can some help me with this issue. On press not working in Flatlist render function. here my code. i checked other screens touch case working fine but when i try it in Flatlist it's not working
render(){
return (
<View style={styles.container} >
<FlatList
data={this.state.categories}
numColumns={2}
keyExtractor={item => item.id}
renderItem={item => this.renderItem(item)}
/>
</View>
);
}
renderItem = ({item,index}) => {
return (
<TouchableOpacity onPress={() => this.moveToLocation(item.id)} style={styles.items}>
<Image source={{uri:item.img}}
resizeMode="center"
style={styles.itemsimg} />
<Text style={{textAlign:'center',fontSize:20, }} onPress={() => this.moveToLocation(item.id)}>{item.name}</Text>
</TouchableOpacity>
);
}
You need to wrap your row element (inside your renderItem method) inside tag. TouchableWithoutFeedback takes onPress as it's prop where you can provide onPress event.
For TouchableWithoutFeedback refer
https://facebook.github.io/react-native/docs/touchablewithoutfeedback.html
if onPress is not workingin the flatlist's render method try using onTouchStart method of the components if they have in the flatList's render method.

React Native, Passing Navigation to Stateless Flatlist component

Currently I have:
return(
<View style={{flex: 1, paddingTop:20}}>
<FlatList
data={this.state.dataSource}
renderItem={(data) => <EventCard eventinfo = {data.item} navigation=
{this.props.navigation}/>}
keyExtractor={(item) => item.eventname}
/>
and
const EventCard = ({eventinfo, navigation}) => {
return (
<TouchableOpacity style={{backgroundColor: 'transparent'}} onPress= {()
=> navigation.navigate('CurrRes')}>
I dont understand why Navigation cant be evaluated in my Eventcard, and navigation doesnt work. Any help would be appreciated.
(yes withnavigation is imported in the first file and the project runs but crashes when one of the flatlist items is pressed)
The error i get is
undefined is not an object (evaluating 'navigation.navigate')
Here is an example I found to explain it better.
You need to access props differently than just a normal function with deconstruction.
const Child = (props) => {
return (
<div style={{backgroundColor: props.eyeColor}} />
)
}
https://medium.com/#PhilipAndrews/react-how-to-access-props-in-a-functional-component-6bd4200b9e0b
Nevermind, I had to export the actual list with navigation so each of its nested stateless components could navigate. Sorry!

How do I render different data types from a fetched json?

I was using...
<FlatList
data={this.state.dataSource}
renderItem={({item}) => <Text>{item.username} {item.name}</Text>}
keyExtractor={({id}, index) => id}
/>
...to render two texts in React Native but now I've got an uri in my json...
How do I render the image in an IM style (thumbnail, username and name)?
Add a renderItem method and then put everything you need in there. Once you make the renderItem method you can throw it into your FlatList.
renderItem({ item }) {
return (
<View>
<Image
source={{uri: item.uri}}
/>
<Text>
{item.username}
</Text>
<Text>
{item.name}
</Text>
</View>
);
}
Then use the method inside the FlatList (the .bind makes sure it stays in the right context)
<FlatList
data={this.state.dataSource}
renderItem={this.renderItem.bind(this)}
keyExtractor={({id}, index) => id}
/>
You can build a component that takes your fields as its props, containing multiple Texts and an Image using your uri as the source. Style this like you would any other component, and then pass that component into renderItem.
You can embed the component immediately to the renderItem like this if the flatlist item is not complicated ( has a lot of component )
<FlatList
data={this.state.dataSource}
renderItem={({item}) => {
<View>
<Image source={{uri: item.uri.image}}/>
<Text>{item.userName}</Text>
<Text>{item.name}</Text>
</View>
}}
keyExtractor={(i) => i.toString()}
/>

React Native FlatList inside ScrollView onEndReached never called

My container is a scrollview and inside it is a flatlist, which load data from server.
The flatlist:
<VirtualizedList
ListEmptyComponent={<NoData />}
data={data}
getItem={(items, index) => items.get(index)}
getItemCount={(items) => items.size}
keyExtractor={(item, index) => String(index)}
renderItem={this._renderItem}
refreshControl={
<RefreshControl
refreshing={loading}
onRefresh={this._onRefresh.bind(this)}
/>
}
onEndReached={this.handleLoadMore}
onEndReachedThreshold={0.1}
onMomentumScrollBegin={() => {
Log('onMomentumScrollBegin fired!')
this.onEndReachedCalledDuringMomentum = false;
}}
/>
which handleLoadMore is:
handleLoadMore = () => {
Log('handleLoadMore fired!');
if (!this.onEndReachedCalledDuringMomentum) {
// fetch data..
this.onEndReachedCalledDuringMomentum = true;
}
}
The problem is the handleLoadMore never called and the onMomentumScrollBegin also never called.
How to solve this?
Actually you don't need to use Content or ScrollView as FlatList has both ListFooterComponent and ListHeaderComponent
In case you really need to use FlatList inside ScrollView, then add style and content contentContainerStyle to your ScrollView or if you use native-base, inside the Content
<ScrollView
...
style={{flex: 1}}
contentContainerStyle={{flex: 1}}
...
/>
Then if you want to use header component out of FlatList loop. Then use ListHeaderComponent={() => <SomeHeader /> inside Flatlist.