Reactjs: Key undefined when accessed as a prop
Asked Answered
C

4

24

Tools: Reactjs 0.14.0 Vanilla Flux

I need unique identifiers for 2 reasons:

  1. Child Reconciliation
  2. Keeping track of what child was clicked

So let's say I have a list of messages that looks like this:

[
    {
      id: 1241241234,  // <-----The unique id is kept here
      authorName: "Nick"
      text: "Hi!"
    },
    ...
]

And now I use a Array.prototype.map() to create "ownee" component (MessageListItem) inside of the owner component MessageSection

function getMessageListItem(message) {
    return (
        <MessageListItem key={message.id} message={message} />
    );
}

var MessageSection = React.createClass({
    render: function() {
        var messageListItems = this.state.messages.map(getMessageListItem);
        <div>
            {messageListItems }
        </div>
    }
});

But the this.props.key is undefined in the MessageListItem even though I know for a fact that is was defined when it was passed down.

var ConvoListItem = React.createClass({
    render: function() {
        console.log(this.props.key); // Undefined
    }
});

I'm guessing there is a reason that React is not letting key be used as a prop.

Question:

If I can't use key as a prop, then what is the proper way to handle the duality need of keying and setting unique identifiers on a dynamic list of child elements that contain state?

Christeenchristel answered 11/11, 2015 at 23:4 Comment(3)
React uses key internally, can you just use a different prop name?Disjuncture
Yes, something like 'key={message.id} myId={message.id}'Andy
So just use the same id twice like @GrigoryKatkov suggests? If everybody agrees, I'll accept that as the answer :) Thanks everybody!Christeenchristel
W
13

It is best to use id. Then in the eventHandler you can have event.target.id.

function getMessageListItem(message) {

  return (
    <MessageListItem key={message.id} id={message.id} message={message}/>
  );
}
Wild answered 11/11, 2015 at 23:23 Comment(0)
S
36

key and ref aren't really 'props'. They're used internally by react and not passed to components as props. Consider passing it as a prop such as 'id'.

Stalinsk answered 11/11, 2015 at 23:9 Comment(0)
W
13

It is best to use id. Then in the eventHandler you can have event.target.id.

function getMessageListItem(message) {

  return (
    <MessageListItem key={message.id} id={message.id} message={message}/>
  );
}
Wild answered 11/11, 2015 at 23:23 Comment(0)
E
2

As we already established in other answers that you can't use key since it isn't passed as a prop and instead used internally by react. Here is my 2 cents as an alternative:
Since you're passing the entire array of messages as a prop while creating the <MessageListItem> component, you don't necessarily need to pass another prop with id. You can simply use {this.props.message.id} whenever you need to use id.

Ezar answered 16/1, 2019 at 1:33 Comment(0)
D
0

As you've discovered, the key property is consumed by React itself, not passed to the child component. It's what React uses to keep track of entries in arrays to avoid unnecessarily re-rendering them (both in terms of calling their render and reconciling with the DOM).

Unfortunately, that means if you also want to use it in the child, you have to pass it twice. In your code, you already are passing it twice (once as key, one as part of message). So you can keep your current JSX, just use id from message in the child:

var MessageListItem = React.createClass({
    render: function() {
        console.log(this.props.message.id);
//                             ^^^^^^^^^^^−−−−− Has the value
    }
});

More:

Dehiscence answered 4/6, 2021 at 17:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.