nachonate
nachonate

Reputation: 11

react native - key not working properly when using Array.prototype.map()

I am using Array.prototype.map() in my React Native code to render some categories in a list, each of which is editable as a TextInput. I am using a unique key at the parent element level to render the mapped array, but I am still get the following error:

Warning: Encountered two children with the same key, [object Object]

The block of code in question is the following:

const CategoriesScreen = ({ navigation }) => {
  // Redux
  const categories = useSelector((state) => state.auth.categories);
  const dispatch = useDispatch();
  
  return (
    <ScrollView style={styles.flex}>
      <View style={styles.container}>
        <View style={styles.textContainer}>
          <Text>Category</Text>
        </View>
        <View style={styles.textContainer}>
          <Text>Update Priority</Text>
        </View>
        <Spacer />
      </View>
      {categories.map((category, index) => {
        return (
          <View key={category.id} style={styles.container}>
            <View style={styles.subContainer}>
              <TextInput
                multiline
                style={styles.textBoxes}
                value={category.name}
                onChangeText={(text) =>
                  dispatch(updateCategoryName({ index, text }))
                }
              />
            </View>
            <View style={styles.subContainer}>
              <View style={styles.icon}>
                <AntDesign
                  name="up"
                  size={24}
                  color="black"
                  onPress={() => dispatch(increasePriority(index))}
                />
              </View>
              <View style={styles.icon}>
                <AntDesign
                  name="down"
                  size={24}
                  color="black"
                  onPress={() => dispatch(decreasePriority(index))}
                />
              </View>
            </View>
            <View style={styles.subContainer}>
              <Feather
                name="delete"
                size={40}
                color="black"
                onPress={() => dispatch(deleteCategory(index))}
              />
            </View>
          </View>
        );
      })}
      <AntDesign
        name="plussquare"
        size={40}
        color="black"
        style={styles.addButtonStyle}
        onPress={() => dispatch(addCategory())}
      />
    </ScrollView>
  );
};

An example of the data array I am mapping:

const categories =  [
  {
    "id": "dc4422e4-1fff-cf90-ce9b-1fd57348cd52",
    "name": "Uncategorized"
  },
  {
    "id": "add5cb6c-53e6-30e7-b9be-b48ad394e216",
    "name": "new1"
  },
  {
    "id": "3fa3cb68-38d5-f54b-2cc0-f0584089c1c2",
    "name": "new2"
  },
]

You can see that each id is completely unique. Would anyone be able to help me understand why I am getting this key error?

Upvotes: 1

Views: 868

Answers (2)

Abdul Kabir
Abdul Kabir

Reputation: 128

You can remove this warning by using index as key

{categories.map((category, index) => {
    return (
      <View key={index.toString()} style={styles.container}>

the warning will disappear.

When you use database id or the object Id the map doesn't know the id is unique so it returns the warning

Upvotes: 0

shahwarishameed
shahwarishameed

Reputation: 11

nachonate

When you are rendering React components in a map function inside the render function, you must provide a key prop to each component that is unique, otherwise React will put a warning in the console and may or may not update your component when it renders.

So the Solution would be a key prop should be unique, stable and reproducible.

 {categories.map((category, index) => {
    return (
      <View category={category} key={category.id} style={styles.container}>
        <View style={styles.subContainer}>
          <TextInput
            multiline
            style={styles.textBoxes}
            value={category.name}
            onChangeText={(text) =>
              dispatch(updateCategoryName({ index, text }))
            }
          

The best practice in situations like this is to use the unique ID backing your objects.

Upvotes: 1

Related Questions