KidCoder
KidCoder

Reputation: 164

React Native Key Problems

So in my react native app for some weird reason my app keeps telling me that Warning: Each child in a list should have a unique "key" prop but why?
Here is the code that shows the problem:

const TabBarIcon = ({ onPress, options, iconName, isFocused }) => {
  return (
    <Pressable
      onPress={() => onPress()}
      testID={options.tabBarTestID}
      accessibilityRole="button"
      style={({ pressed }) => [
        styles.bottomTabNavigationButtonStyling,
        {
          backgroundColor: pressed ? 'rgba(255, 255, 255, 0.28)' : '#EA3345',
        },
      ]}>
      {isFocused ? (
        <Icon name={iconName} size={RFPercentage(5)} color="white" />
      ) : (
        <Icon name={iconName} size={RFPercentage(4)} color="white" />
      )}
    </Pressable>
  );
};

const MyTabBar = ({ state, descriptors, navigation }) => {
  return (
    <View style={styles.bottomTabNavigatorStyling}>
      {state.routes.map((route, index) => {
        const isFocused = state.index === index;
        const { options } = descriptors[route.key];

        const onPress = () => {
          const event = navigation.emit({
            type: 'tabPress',
            target: route.key,
          });
          if (!isFocused && !event.defaultPrevented) {
            navigation.navigate(route.name);
          }
        };

        return (
          <>
            /****************************************Problem Part
            {index === 0 && (
              <TabBarIcon
                key="home"
                onPress={() => onPress()}
                options={options}
                iconName="home"
                isFocused={isFocused}
              />
            )}
            {index === 1 && (
              <TabBarIcon
                key="tasks"
                onPress={() => onPress()}
                options={options}
                iconName="tasks"
                isFocused={isFocused}
              />
            )}
            {index === 2 && (
              <TabBarIcon
                key="statistics"
                onPress={() => onPress()}
                options={options}
                iconName="history"
                isFocused={isFocused}
              />
            )}
            /*******************************************
          </>
        );
      })}
    </View>
  );
};

please tell me what is happening. And if I forgot to mention something please do tell. I have sort bordered the part were it shows the error. It keeps saying that Each child in a list should have a unique key even thought my items are not in a list? And even if they were in a list, the key property is completely diffrent so why the problem?

Upvotes: 1

Views: 153

Answers (1)

amirhosein vakilpoor
amirhosein vakilpoor

Reputation: 26

You have to put the key prop on the top element. in your case you have to set key prop on <React.Fragment>, TabBarIcon is not the top element.

for example you can do it like below

return (
  <React.Fragment key={'route'+index}>
    /****************************************Problem Part
    {index === 0 && (
      <TabBarIcon
        onPress={() => onPress()}
        options={options}
        iconName="home"
        isFocused={isFocused}
      />
    )}
    {index === 1 && (
      <TabBarIcon
        onPress={() => onPress()}
        options={options}
        iconName="tasks"
        isFocused={isFocused}
      />
    )}
    {index === 2 && (
      <TabBarIcon
        onPress={() => onPress()}
        options={options}
        iconName="history"
        isFocused={isFocused}
      />
    )}
    /*******************************************
  </React.Fragment>
);

you can also do the same with FlatList MyTabBar component would be something like this

const MyTabBar = ({ state, descriptors, navigation }) => {
  const _renderItem = ({ route, index }) => {
    const isFocused = state.index === index;
    const { options } = descriptors[route.key];

    const onPress = () => {
      const event = navigation.emit({
        type: 'tabPress',
        target: route.key,
      });
      if (!isFocused && !event.defaultPrevented) {
        navigation.navigate(route.name);
      }
    };
    return (
      <TabBarIcon
        key="home"
        onPress={() => onPress()}
        options={options}
        iconName="home"
        isFocused={isFocused}
      />
    );
  };
  return (
    <View style={styles.bottomTabNavigatorStyling}>
      <FlatList
        data={state.routes}
        renderItem={_renderItem}
        keyExtractor={(item, index) => 'TabBarIcon' + index}
      />
    </View>
  );
};

Upvotes: 1

Related Questions