I can't understand why i get this warning when i have a unique key set. The warning only shows when reloading the app (R button in metro).
If i click back and forward or refresh the screen by scrolling it does not show the warning. I have tried both setting a index as below but also adding random Math numbers in a loop but the warning still shows.
The app works as intended but the warning really annoys me. I have been struggling with this for days now and all help is appreciated.
The warning:
ERROR Warning: Each child in a list should have a unique "key" prop.
Check the render method of `GameScreen`. See https://reactjs.org/link/warning-keys for more information.
My code:
import React, {useEffect, useState} from 'react';
// more imports
function GameScreen({navigation, route}){
let loadingView = [];
// more not so important consts
const [data_opponentInfo, setData_opponentInfo] = useState([null,null,null]);
const [data_game, setData_game] = useState({rounds: {}, info: {}});
const [isLoading, setIsLoading] = useState(true);
const [refreshing, setRefreshing] = useState(false);
const wait = (timeout) => {
return new Promise(resolve => setTimeout(resolve, timeout));
}
const onRefresh = React.useCallback(() => {
setRefreshing(true);
loadMatchData();
wait(1000).then(() => setRefreshing(false));
}, []);
const loadMatchData = () => {
// fetch here to get data from api and populate setData_game() and setData_opponentInfo()
};
useEffect(() => {
loadMatchData();
}, []);
for (var x = 0; x < 6; x ){
if (x == 0){
loadingView.push(<View style={[styles.loading,{borderBottomColor:'transparent'}]}><Spinner type="Radial" color="#fff" size={40} /></View>);
} else if (x == 5) {
loadingView.push(<View style={[styles.loading,{borderBottomColor:'rgba(255,255,255,0.8)'}]}></View>);
} else {
loadingView.push(<View style={[styles.loading,{borderBottomColor:'transparent'}]}></View>);
}
}
const list_rounds = Object.keys(data_game.rounds).map((item, index) => {
// defining not important vars here
// defining variables content_left and content_right here
return (
<React.Fragment key={index}>
<View style={[styles.content_item_row,{backgroundColor: row_background}]}>
{content_left}
<View style={styles.content_center_wrapper}>
<View style={[styles.content_center_round_wrapper,{backgroundColor:round_num_background}]}>
<Text style={styles.content_center_round_text}>{item}</Text>
</View>
<View style={styles.content_center_category_wrapper}>
<Text style={styles.content_center_category_text}>{round_delta}</Text>
</View>
</View>
{content_right}
</View>
</React.Fragment>
)
});
return (
<View style={{flex:1}}>
{isLoading ? loadingView : list_rounds}
</View>
)
}
export default GameOverviewScreen;
const styles = StyleSheet.create({
// Styles here
});
CodePudding user response:
To avoid refresh all components when data change, you should use "key" attribute for your component.
if (x == 0){
loadingView.push(<View key={`view_${i}`} style={[styles.loading,{borderBottomColor:'transparent'}]}><Spinner type="Radial" color="#fff" size={40} /></View>);
The best practice is to use a unique id and not an index as in this case.