Why does React need a key prop?

Why does React need a key prop?

If you have used React for your project you must have noticed one thing. React has such a big problem with arrays. So, in this article, we will see why does React need a key prop.

Why does React need a key prop?

If you’ve used React for a while, you’ve probably run into this before:

index.js:1 Warning: Each child in a list should have a unique “key” prop.


Check the render method of `App`. See https://reactjs.org/link/warning-keys for more information.


at li


at App (http://localhost:3000/static/js/30.chunk.js:48:75)

 

Also, you probably know the solution as well. Here’s the rule:

Whenever you’re rendering an array of React elements, each one must have a unique key prop. So, here’s the simplest way to reproduce this problem:

const items = [


{id: ‘apple’, value: ‘apple’},


{id: ‘orange’, value: ‘orange’},


{id: ‘grape’, value: ‘grape’},


{id: ‘pear’, value: ‘pear’},


]


function App() {


return (


<ul>


{items.map((item) => (


<li>{item.value}</li>


))}


</ul>


)


}

 

But the solution is pretty simple:

– <li>{item.value}</li>


+ <li key={item.id}>{item.value}</li>

 

But why React doesn’t seem to have a problem if we were to write it like this:

function App() {


return (


<ul> <li>apple</li>


<li>orange</li>


<li>grape</li>


<li>pear</li>


</ul>


)


}

 

It’s only a problem if we try to pass the elements as an array. So, why does React have such a big problem with arrays anyway? Firstly, if you want to understand what problems can happen without the key prop, read Understanding React’s key prop. However, in this post, we just want to explain why React can’t just make things work without a key prop.

Let’s pretend you’re React and we are a React developer building an application. So, we are writing a function component called App. However, you don’t get to see my implementation, all you get is the function from which you can pass arguments and receive a return value. So let’s say we give you that function and tell you to render that to the page. After that, you call App and you get the following React elements back (learn more about React elements):

const element = {


type: ‘ul’,


key: null,


props: {


children: [


{type: ‘li’, key: null, props: {children: ‘apple’}},


{type: ‘li’, key: null, props: {children: ‘orange’}},


{type: ‘li’, key: null, props: {children: ‘grape’}},


{type: ‘li’, key: null, props: {children: ‘pear’}},


],


},


}

 

But first, you’re going to warn right? Because the key is null for all of those children. But you know how to take these elements and render them to the page. In addition, you render the ul and li to the page. So, now my App calls a state updater function and so you know you need to re-render. Also, you call App again and this time you get some new React elements:

const element = {


type: ‘ul’,


key: null,


props: {


children: [


{type: ‘li’, key: null, props: {children: ‘apple’}},


{type: ‘li’, key: null, props: {children: ‘orange’}},


{type: ‘li’, key: null, props: {children: ‘pear’}},


],


},


}

 

So, you do a quick and easy diff here:

– {type: ‘li’, key: null, props: {children: ‘grape’}}

 

Also, you need another state update, so you get the next set of React elements:

const element = {


type: ‘ul’,


key: null,


props: {


children: [


{type: ‘li’, key: null, props: {children: ‘apple’}},


{type: ‘li’, key: null, props: {children: ‘pear’}},


],


},


}

 

Now do another diff:

– {type: ‘li’, key: null, props: {children: ‘apple’}},


– {type: ‘li’, key: null, props: {children: ‘orange’}},


+ {type: ‘li’, key: null, props: {children: ‘apple’}},

 

However, interestingly this means that rather than just unmounting the grape li on that first state update, you actually unmounted pear and updated grape to say pear. Unmounting and mounting components have implications on the state and side-effects of a component.

And that also means with this last state update, you unmounted pear again and updated apple to be apple and orange got updated to say pear. This is definitely not the most optimal, but what are you gonna do? You have no idea what is with the element change!

Now comes the ‘key’ prop

What if you have some way to track the React elements from one render to the next so your diff could be more informative. That way you’d know intent much better.

const element = {


type: ‘ul’,


key: null,


props: {


children: [


{type: ‘li’, key: ‘apple’, props: {children: ‘apple’}},


{type: ‘li’, key: ‘orange’, props: {children: ‘orange’}},


{type: ‘li’, key: ‘pear’, props: {children: ‘pear’}},


],


},


}

 

So, now here comes the update for you:

const element = {


type: ‘ul’,


key: null,


props: {


children: [


{type: ‘li’, key: ‘apple’, props: {children: ‘apple’}},


{type: ‘li’, key: ‘pear’, props: {children: ‘pear’}},


],


},


}

 

So, now you know exactly what to do.  In addition, you can now do a much more granular diff. Firstly, you notice that the element with the keyof 'orange' is gone. So you know you can remove that from the page. Also, the element with the key of 'apple' has new children.So you can simply update it and move on without worrying about whether you’re doing the right thing.

Conclusion

So, in this article, we discussed why does React needs a key prop. Feel free to comment with your suggestions and feedback. At BOSC Tech Labs, we have a team of highly experienced React JS developers who can assist you in developing your customized web app. So contact us to hire experienced React JS developers.

Request a Quote