I’m new to React Native and running into this error that I can’t figure out despite sufficient research. I’m setting the key prop on some TextInput fields before pushing them into an array. However, it’s still throwing an error when I try to render these entries in the return function.
‘ Each child in a list should have a unique "key" prop. ‘ … Check the render method of WordInput
.
import { useState } from 'react';
import styles from '../styles/styles';
import { Text, TextInput, View, Pressable, Dimensions, SafeAreaView, StyleSheet, ScrollView, TouchableOpacity, StrictMode } from 'react-native';
export default function WordInput({ navigation }) {
var Inputs = new Array();
var Words = new Array();
for (let i = 0; i < 12; i++) {
let key = i;
Inputs[i] = <TextInput key={key} style={styles.input} placeholder="word" onChangeText={(value) => insertWord(value, i)}/>
console.log(Inputs[i]);
}
const insertWord = async (value, index) => {
Words[index] = value;
}
const wordsSubmit = async () => {
console.log("Done");
}
return (
<View style={styles.container}>
<ScrollView>
<View style={styles.header}>
<Text style={{textAlign: 'center', fontSize: 30}}>Enter Words:</Text>
{Inputs.map((row, index) => {
return (
<View>
<Text>{index+1}.</Text>
{row}
</View>
);
})}
<Pressable style={styles.button} onPress={() => wordsSubmit()}>
<Text style={styles.buttonText}>Submit</Text>
</Pressable>
</View>
</ScrollView>
</View>
)
}
I’ve tried setting the key value both using the index i of the for loop directly as key={i} and via another variable, which was the suggested on another post: e.g. let key = i; key={key}. Neither is working. In addition, when I print each Array entry out to console none of them contain the key attribute that’s being set in the loop.
LOG <TextInput onChangeText={[Function onChangeText]} placeholder="word" style={{"borderWidth": 1, "height": 40, "margin": 12, "padding": 5}} />
LOG <TextInput onChangeText={[Function onChangeText]} placeholder="word" style={{"borderWidth": 1, "height": 40, "margin": 12, "padding": 5}} />
LOG <TextInput onChangeText={[Function onChangeText]} placeholder="word" style={{"borderWidth": 1, "height": 40, "margin": 12, "padding": 5}} />
LOG <TextInput onChangeText={[Function onChangeText]} placeholder="word" style={{"borderWidth": 1, "height": 40, "margin": 12, "padding": 5}} />
The page still renders the way I want (testbed) and I don’t need the key prop for any functionality so a workaround would also be welcomed. I would really like to understand why this is happening so I can learn from it and fix it. Code below…
2
Answers
It’s the
.map
you’re doing in the JSX.You need to give the top level element a key prop when you’re rendering from an array:
More info here: https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key
Also as a side note, it’s usually okay to use the index as a key, but if the order of the data will change for any reason you should give the key something that is unique to the data that you’re mapping such as an ID otherwise the performance benefits that React is giving you will be lost. Read more in the docs I linked.
This is where you’re rendering a list:
And the child of that list (
<View>
) indeed has nokey
prop. Add one:Ideally the key isn’t just the list index, but is instead a meaningful unique property from the element in the list (from
row
in this case), but in most simple cases it doesn’t make a noticeable difference.