I have a screen in which I display a list of products. I am trying to set up a pagination. I am using List item from react-native-elements and looking at Using RN FlatList as possible in the documentation for this package.
I set up the ability to do pagination, but I got confused in my code. I don't know how to fix it anymore. I would like to know if it would be possible for you to give me a boost and reread my code to give me your opinion.
There for the moment I have the error:
Each child in a list should have a unique "key" prop
I'm a bit lost and need some guidance please. Thanks for any explanation.
The code :
export default class Products extends Component {
constructor(props) {
super(props);
this.state = {
productId: (props.route.params && props.route.params.productId ? props.route.params.productId : -1),
listData: '',
currentPage: 1,
loadMoreVisible: true,
loadMoreVisibleAtEnd: false,
displayArray: []
}
};
initListData = async () => {
let list = await getProducts(1);
if (list) {
this.setState({
displayArray: list,
loadMoreVisible: (list.length >= 10 ? true : false),
currentPage: 2
});
}
};
setNewData = async (page) => {
let list = await getProducts(parseInt(page));
if (list) {
this.setState({
displayArray: this.state.displayArray.concat(list),
loadMoreVisible: (list.length >= 10 ? true : false),
loadMoreVisibleAtEnd: false,
currentPage: parseInt(page)+1
});
}
};
loadMore() {
this.setNewData(this.state.currentPage);
}
displayBtnLoadMore() {
this.setState({
loadMoreVisibleAtEnd: true
});
}
async UNSAFE_componentWillMount() {
this.initListData();
}
renderItem = ({ item, i }) => (
<ListItem key={i}
bottomDivider
containerStyle={{backgroundColor: i % 2 === 0 ? '#fde3a7' : '#fff' }}
onPress={() => this.props.navigation.navigate('ProductDetails', {productId:parseInt(item.id)})}>
<Icon name='shopping-cart' />
<ListItem.Title style={{width: '65%', fontSize: 14, color: i % 2 === 0 ? '#212121' : '#F78400' }}>{item.name}</ListItem.Title>
<ListItem.Subtitle style={{ color: '#F78400'}}>{i18n.t("information.cost")}:{item.cost}</ListItem.Subtitle>
</ListItem>
);
render() {
//console.log('displayArray', this.state.displayArray)
return (
<View style={{flex: 1}}>
{this.state.displayArray !== null && this.state.displayArray.length > 0 ? (
<View style={{ flex: 1}}>
<SafeAreaView>
{
this.state.displayArray.map((item, i) => (
<FlatList
keyExtractor={(item, i) => {
return item.id;
}}
data={this.state.displayArray}
onEndReached={() => this.displayBtnLoadMore()}
renderItem={this.renderItem}
/>
))
}
</SafeAreaView>
{this.state.loadMoreVisible === true && this.state.loadMoreVisibleAtEnd === true ? (
<Button title=" + " onPress={()=>{this.loadMore()}}></Button>
) : null
}
<View style={styles.container}>
<Text>{"\n"}</Text>
<TouchableOpacity
style={styles.touchable2}
onPress={() => this.props.navigation.goBack()}
>
<View style={styles.container}>
<Button
color="#F78400"
title= 'Back'
onPress={() => this.props.navigation.goBack()}>BACK
</Button>
</View>
</TouchableOpacity>
</View>
<Text>{"\n\n"}</Text>
</View>
) : (
<View style={styles.container}>
<Text>{"\n\n" + (this.state.displayArray === null ? i18n.t("products.searching") : i18n.t("products.nodata")) + "\n\n\n"}</Text>
<Button
color="#F78400"
title= 'Back'
onPress={() => this.props.navigation.goBack()}>BACK
</Button>
</View>
)}
</View>
);
};
}
The problem is not in your list items but in the FlatList
itself - you are rendering an array of FlatList
components but they don't have unique keys.
this.state.displayArray.map((item, i) => (
<FlatList
key={item.id} // or key={i} if item doesn't have ID
... rest of your flat list props
/>
))