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?

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
Nick Pineda
  • 6,354
  • 11
  • 46
  • 66

4 Answers4

35

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'.

Brigand
  • 84,529
  • 20
  • 165
  • 173
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}/>
  );
}
bertdida
  • 4,988
  • 2
  • 16
  • 22
J. Mark Stevens
  • 4,911
  • 2
  • 13
  • 18
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.

Rakshit Sinha
  • 31
  • 1
  • 5
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:

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875