i have a flatlist and 5 items I want every item to navigate different pages
but currently it gives me an error
<FlatList style={{backgroundColor:'#ffffff'}}
data={[{key: 'Book',details:'sssss',icon:'ios-calendar-outline',way:'Home'}]}
renderItem={({item}) => <TouchableOpacity onPress={() => navigate({item.way})}>
how can I pass {item.way} variable into navigate()
You have a syntax error here navigate({item.way}). Try:
navigate(item.way)
Related
Each item within my flat list is a touchable opacity (an icon). I would like a function to execute when an icon is tapped. This function has been passed as a prop from the parent component and I'm passing the icon data into that prop. I thought this would be straight forward. However when I tap on the icon to open the modal that contains my flat list, the modal doesn't open and I get a warning: 'Cannot update a component from inside the function body of a different component.' I'm confused because I'm executing a function that has been passed as a prop from my parent component. I'm unsure how else I am supposed to do it?
This is the function I want to call on tap (the changeIcon prop is the one causing the issues):
function chosenIcon(selectedIcon) {
props.changeIcon(selectedIcon);
props.closeIconList(false);
}
This is the FlatList, and it doesn't seem to like me passing item.item.icon.
<FlatList
numColumns={3}
data={ICONS}
renderItem={(item) => (
<TouchableOpacity style={styles.item} onPress={chosenIcon(item.item.icon)}>
<Text style={styles.text}>{item.item.icon}</Text>
</TouchableOpacity>
)}
/>
If I comment out the props.changeIcon line in the function and don't pass the data item.item.icon, everything works fine and the modal closes when I select an icon.
I hope that's clear enough! Thank you!
Please try to add a fat arrow function to TouchableOpacity onPress callback.
<FlatList
numColumns = {3}
data = {ICONS}
renderItem = {item => (
<TouchableOpacity style = {styles.item} onPress= {()=> chosenIcon(item.item.icon)}> // add ()=>
<Text style = {styles.text}>{item.item.icon}</Text>
</TouchableOpacity>
)}
/>
I have a FlatList:
<ScrollView nestedScrollEnabled={true}>
<Screen style={styles.screen}>
<TouchableOpacity onPress={() => navigation.navigate("ProfileDetailScreen")}>
<FlatList
data={users}
renderItem={renderItem}
keyExtractor={item => item.uid}
/>
</TouchableOpacity>
</Screen>
</ScrollView>
And Im getting some data from firebase like:
useEffect(() => {
firebaseUsers
.onSnapshot(
querySnapshot => {
const newUsers = []
querySnapshot.forEach(doc => {
const user = doc.data()
user.id = doc.id
newUsers.push(user)
});
setUsers(newUsers)
},
error => {
console.log(error)
}
)
}, [])
The data I get from firebase has name, image and age (and more more fields).
How can I pass all the data for a single user into the ProfileDetailedScreen?
Not sure the correct way to achieve this (not sure If I need to create data models etc?)
I don't know firebase that well but I have experience in RN. From what I'm understanding, you're going to want to make the renderItem function in your FlatList a function that returns a TouchableOpacity with navigation to the ProfileDetailedScreen component while also passing the user object. You'll display the user details in the ProfileDetailedScreen.
Passing items in navigation documentation
/* 'item' is a user from the users array you passed into the data property of your FlatList above */
renderItem = ({item}) => (
<TouchableOpacity onPress={() => navigation.navigate("ProfileDetailScreen", item)}>
<Text> item?.name </Text> {/* show brief info about user */}
</TouchableOpacity>
)
If you're using Redux for your application state, you could also navigate only to "ProfileDetailScreen" and dispatch an action that sets a currentUser in state. Your "ProfileDetailsScreen" would then pull the currentUser from state. This way has more moving parts but the component piece would look something like this:
/* 'item' is a user from the users array you passed into the data property in your FlatList above */
renderItem = ({item}) => (
<TouchableOpacity onPress={this.setUserAndNavigate.bind(this, item)}>
<Text> item?.name </Text> {/* show brief info about user */}
</TouchableOpacity>
)
setUserAndNavigate = (user) => {
this.props.setUser(user);
navigation.navigate("ProfileDetailScreen");
}
I have been trying to navigate to the same screen with different parameters on react-native application. It is a category screen, where I don't want the user to go back and select different categories to view products. I have made a screen where products from categories are displayed.
Below is my code:
<View style={styles.horizontalSlider}>
<FlatList
horizontal
showsHorizontalScrollIndicator={false}
data={this.state.DataSource}
keyExtractor={(item, index) => index.toString()}
extraData={this.state.selectedItem}
renderItem= { ({item}) => (
<TouchableOpacity onPress={(category) => navigate.push('CategoryScreen', {item})}>
<ImageBackground style={styles.profileImgContainer} >
<Image source={{ uri: item.images }} style={[styles.profileImg, , { borderColor: 'green', borderWidth:2 }]} />
</ImageBackground>
</TouchableOpacity>
)}
/>
</View>
If you want to navigate to the same screen with different parameters and be unable to go back, use this.props.navigation.replace('CategoryScreen', { ...new params here... })
If you want to change current navigation params without navigating, use this.props.navigation.setParams()
(navigation prop)
But your problem is not a navigation problem. You don't need multiple screens for that. Solve it with react. All you need to do is to render your list conditionally depending on what category (or circle item?) is currently selected. Store this information in state and use it in render
You can add unique key:
this.props.navigation.navigate({ routeName: route, params: params, key: route + params.id })
I have a FlatList component that renders 20 items. When I load up the page in React Native, my FlatList shows 10 items. Once a render has occurred, the next 10 are loaded.
<FlatList
data={data}
keyExtractor={(item, i) => String(i)}
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.boardList}
renderItem={({ item, index }) => (
<Item {...item}/>
)}
/>
data is simply an Array of JSON objects.
You should set following properties
initialNumToRender={20}
maxToRenderPerBatch={20}
As the default is 10
It may be better to use ScrollView and .map(() = > {}) ?
Add style={{ flex: 1 }} in FlatList
Gist: Dashboard.js
I am creating an iOS application with React-Native, I get this error when my Dashboard.js is rendered.
My Dashboard.js renders different scrollableTabView's which each contain a ListView, I have included some code from one list item below.
renderArchiveOrder(order) {
return (
<TouchableHighlight onPress={this.onPress.bind(order.id)}>
<View style={styles.listObject}>
<View style={styles.thumbnail}>
<Text style={styles.title}>#{order.bid}</Text>
<Text style={styles.time}>TID</Text>
<Text style={styles.subTime}>{order.time}</Text>
</View>
<View style={styles.information}>
<Text style={styles.restaurantName}>{title}</Text>
<Text style={styles.dropoffName>{order.locations.dropoff.address}</Text>
</View>
</View>
</TouchableHighlight>
);
}
My problem is that when Dashboard.js is rendered, the app crashes and the included screenshot is being shown.
It clearly states that renderArchiveOrder: Dashboard.js # 364:0 is throwing an error, here's my onPress function.
I can't understand my error is line 364, and why my TouchableHighlight onPress doesn't work.
id: index is line 364.
onPress = (index) => {
this.props.navigator.push({
title: 'Order',
component: Order,
passProps: {
id: index
}
})
};
Why does this occur when I'm just trying to send data to a click function and push the navigator to a new view?
Since you're passing your renderArchiveOrder method as a value to another component, it loses its context. Thus, the this variable inside your method will not refer to your component instance, and trying to access this.onPress will yield undefined.
To fix this, simply bind your method to your component instance before passing it to your ListView component:
<ListView
dataSource={this.state.archiveDataSource}
renderRow={this.renderArchiveOrder.bind(this)}
style={styles.listView}/>