Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warning: Failed child context type: Invalid child context virtualizedCell.cellKey of type number supplied to CellRenderer, expected string. #18291

Closed
ravirajn22 opened this issue Mar 9, 2018 · 15 comments
Labels
Ran Commands One of our bots successfully processed a command. Resolution: Locked This issue was locked by the bot.

Comments

@ravirajn22
Copy link

Getting the below warning when I use FlatList and where keyExtractor returns a number.

Warning: Failed child context type: Invalid child context `virtualizedCell.cellKey` of type `number` supplied to `CellRenderer`, expected `string`.
    in CellRenderer (created by VirtualizedList)
    in RCTScrollContentView (created by ScrollView)
    in RCTScrollView (created by ScrollView)
    in ScrollView (created by VirtualizedList)
    in VirtualizedList (created by FlatList)

Sample Code for reproduction

import React, { Component } from 'react';
import { Text, View, FlatList } from 'react-native';

export default class NotificationSettingsScreen extends Component {
  render() {
    return (
      <View style={{flex: 1, paddingTop: 36}}>
        <FlatList
          data={[1, 2, 3, 4, 5]}
          renderItem={({item}) => (
            <View>
              <Text>{item}</Text>
            </View>
          )}
          keyExtractor={(item) => item }
        />
      </View>
    );
  }
}

NOTE: Changing keyExtractor={(item) => item.toString()} makes this warning disappear.

Environment

React-Native: 0.53.0,
react: 16.2.0

Expected Behavior

keyExtractor of FlatList must accept number instead of just string

Actual Behavior

Warning when using keyExtractor which returns number

Steps to Reproduce

Check above lines

The above problem could also be due to this commit a010a0c but not sure ...

@react-native-bot
Copy link
Collaborator

Thanks for posting this! It looks like your issue may refer to an older version of React Native. Can you reproduce the issue on the latest stable release?

Thank you for your contributions.

How to ContributeWhat to Expect from Maintainers

@react-native-bot react-native-bot added Old Version Ran Commands One of our bots successfully processed a command. labels Mar 9, 2018
@hramos
Copy link
Contributor

hramos commented Mar 9, 2018

The prop expects a string but you're setting a number. This seems to be working as expected.

@hramos hramos closed this as completed Mar 9, 2018
@ravirajn22
Copy link
Author

Ya I got it , that it requires a string. Wanted to just confirm was it some minor regression or planned change because many use index as keys which will be number. Also I could not find this change in release notes. But anyways thanks for the clarity .

@Baskerville42
Copy link

@ravirajn22 Using index as the key is bad practice. You can use `keyExtractor = (item, index) => 'list-item-${index}'.

@James2516
Copy link

What's the rationale behind this change? Many apps use an unique number id (eg. user id, item id) as the key. Why require it to be cast to a string?

@peacechen
Copy link

"Using index as the key is bad practice."

Which pattern or practice is that violating?

@rfw
Copy link

rfw commented May 12, 2018

keyExtractor = { (item, index) => index.toString() };

The value of keyExtractor must be a string。

@PatriceVignola
Copy link
Contributor

PatriceVignola commented May 15, 2018

@peacechen I think this is one of the reasons. I don't know what the specifics are but, even though it's an article about React, I wouldn't be surprised if it's a problem on React Native too.

The way I understand it, keys help with identifying objects throughout multiple renders, so if you remove and re-add an object to the list, it should recognize it by its key. It might also be a way to improve performance by finding the cached item and rendering it instead of creating a new one. Having an index (0,1,2,3,etc.) defeats this purpose. The AirBnB style guide also discourages the use of index as keys by quoting this article.

@peacechen
Copy link

@PatriceVignola Thanks for the article. It's not convincing though. While strings may offer the potential for better uniqueness, there's no guarantee that every single string key will be unique within the app. In my app there are multiple FlatLists, and within them there can instances of component A that end up with the same string key between those FlatLists.

Ok, so let's assume that the keys are isolated between each FlatList. If that is true, then integer index keys shouldn't be an issue as far as uniqueness.

If each entry's key must be globally unique, no matter where it lives, then React/RN relies on app developers to generate a unique random number (aka hash) that has little or nothing to do with the instance. If that really is the case, then React/RN might as well just internally generate a unique hash for each item in the FlatList, if that is so critical to React rendering.

@tuononh
Copy link

tuononh commented Jul 5, 2018

Why we can use index as key in SectionList?

@mdev0987
Copy link

keyExtractor = { (item, index) => index.toString() };

The value of keyExtractor must be a string。

It works well.

@joakimsandqvistdev
Copy link

joakimsandqvistdev commented Sep 17, 2018

"Using index as the key is bad practice."

Which pattern or practice is that violating?

Its not really a bad practice. Its totally wrong.

When you remove an item from the array the indexes might change and the List component no longer works as intended. The List component will reuse a component that just left the screen and will use that component for the new item that appeared on the other side of the screen. This is why the key must not change in run-time. For this reason, using the index of the array is wrong.

Edit: This is just a hunch. I'm not 100% sure how the ListItem recycling works.

@faddah
Copy link

faddah commented Sep 28, 2018

We ran into this error in an App for a client using <FlatList> today. Very grateful this thread was here or we would have been totally lost.

@peacechen
Copy link

peacechen commented Sep 28, 2018

Its not really a bad practice. Its totally wrong.

When you remove an item from the array the indexes might change and the List component no longer works as intended. The List component will reuse a component that just left the screen and will use that component for the new item that appeared on the other side of the screen. This is why the key must not change in run-time. For this reason, using the index of the array is wrong.

Edit: This is just a hunch. I'm not 100% sure how the ListItem recycling works.

This is less about whether keys should be unique, but rather why this task was delegated to app developers. Since the key is crucial for row recycling, FlatList should handle key assignments internally with a GUID or similar unique hash. Having apps do this is just inviting trouble. I've not found the keys to be useful for the app itself (such as identifying particular rows during runtime; it's better to use the row data for identification), so there shouldn't be much concern if the keys are opaque. Also, looking at other parts of React, there are internally generated unique identifiers for components. Put a breakpoint in your app and poke around at the instantiated components.

It would be helpful for the FlatList author to chime in here.

@benhartouz
Copy link

keyExtractor = { (item, index) => index.toString() };
this woked very well

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Ran Commands One of our bots successfully processed a command. Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests