Extracting Components with Keys

Consider a situation where you have created a separate component for list items and you are extracting list items from that component. In that case you will have to assign keys to the component you are returning from the iterator and not to the list items. That is you should assign keys to <Component /> and not to <li> A good practice to avoid mistake is to keep in mind that anything you are returning from inside of map() function is needed to be assigned key.

Keys only make sense in the context of the surrounding array. For example, if you extract a ListItem component, you should keep the key on the <ListItem /> elements in the array rather than on the <li> element in the ListItem itself.

Example: Incorrect Key Usage

function ListItem(props) {

const value = props.value;

return (

// Wrong! There is no need to specify the key here:

<li key={value.toString()}>

{value}

</li>

);

}

function NumberList(props) {

const numbers = props.numbers;

const listItems = numbers.map((number) =>

// Wrong! The key should have been specified here:

<ListItem value={number} />

);

return (

<ul>

{listItems}

</ul>

);

}

const numbers = [1, 2, 3, 4, 5];

ReactDOM.render(

<NumberList numbers={numbers} />,

document.getElementById(‘root’)

);

Example: Correct Key Usage

function ListItem(props) {

// Correct! There is no need to specify the key here:

return <li>{props.value}</li>;

}

function NumberList(props) {

const numbers = props.numbers;

const listItems = numbers.map((number) =>

// Correct! Key should be specified inside the array.

<ListItem key={number.toString()}

value={number} />

);

return (

<ul>

{listItems}

</ul>

);

}

const numbers = [1, 2, 3, 4, 5];

ReactDOM.render(

<NumberList numbers={numbers} />,

document.getElementById(‘root’)

);

A good rule of thumb is that elements inside the map() call need keys.

Keys Must Only Be Unique Among Siblings

Keys used within arrays should be unique among their siblings. However they don’t need to be globally unique. We can use the same keys when we produce two different arrays:

function Blog(props) {

const sidebar = (

<ul>

{props.posts.map((post) =>

<li key={post.id}>

{post.title}

</li>

)}

</ul>

);

const content = props.posts.map((post) =>

<div key={post.id}>

<h3>{post.title}</h3>

<p>{post.content}</p>

</div>

);

return (

<div>

{sidebar}

<hr />

{content}

</div>

);

}

const posts = [

{id: 1, title: ‘Hello World’, content: ‘Welcome to learning React!’},

{id: 2, title: ‘Installation’, content: ‘You can install React from npm.’}

];

ReactDOM.render(

<Blog posts={posts} />,

document.getElementById(‘root’)

);

Keys serve as a hint to React but they don’t get passed to your components. If you need the same value in your component, pass it explicitly as a prop with a different name:

const content = posts.map((post) =>

<Post

key={post.id}

id={post.id}

title={post.title} />

);

With the example above, the Post component can read props.id, but not props.key.

Embedding map() in JSX

In the examples above we declared a separate listItems variable and included it in JSX:

function NumberList(props) {

const numbers = props.numbers;

const listItems = numbers.map((number) =>

<ListItem key={number.toString()}

value={number} />

);

return (

<ul>

{listItems}

</ul>

);

}

JSX allows embedding any expression in curly braces so we could inline the map() result:

function NumberList(props) {

const numbers = props.numbers;

return (

<ul>

{numbers.map((number) =>

<ListItem key={number.toString()}

value={number} />

)}

</ul>

);

}

Share this post
[social_warfare]
Keys
ReactJS Routing

Get industry recognized certification – Contact us

keyboard_arrow_up