Reputation: 3274
React newbie here. Im referring this and following traversy react videos and i have customized my app with bootstrap4.5. I understand unique key must be passed for performance and help React identify changed items. I have Users.js
1 const Users = (props) => {
2 //class changed to arrow functions
3 if (props.loading) {
4 return <Spinner />
5 }
6 else {
7 return (
8 <div className="row">
9 {props.users.map((user) => (
10 <div className="col-sm-3 mt-3" >
11 <UserItem key={user.id} user={user} />
12 </div>
13 ))}
14 </div >
15 );
16 }
17 }
in above code i get the error in console below:
Warning: Each child in a list should have a unique "key" prop. Check the render method of `Users`. See https://reactjs.org/docs/lists-and-keys.html#keys for more information.
if i change lines 10 and 11 like below, the error is no longer there
10 <div key={user.id} className="col-sm-3 mt-3" >
11 <UserItem user={user} />
Whats the reason behind this and is it fine to pass key like this since it works ?
The list looks like below which is passed in props
[
{
"login": "mojombo",
"id": 17,
"avatar_url": "https://avatars0.githubusercontent.com/u/1?v=4",
"url": "https://api.github.com/users/mojombo",
"html_url": "https://github.com/mojombo"
},
{
"login": "wintersword",
"id": 18,
"avatar_url": "https://avatars0.githubusercontent.com/u/1?v=4",
"url": "https://api.github.com/users/mojombo",
"html_url": "https://github.com/mojombo"
}
]
react version : "16.13.1"
Upvotes: 2
Views: 81
Reputation: 29282
key
should be added on the outer most element in the hierarchy of jsx
code that is created using a loop
From the docs:
Keys only make sense in the context of the surrounding array
To understand it better, lets look at an example.
Suppose you are rendering li
elements using a loop.
const list = tasks.map((t, index) =>
<li key={index}>
{t}
</li>
);
in this case, key
should be on the li
element. Now if you extract li
element in another component, lets say ListItem
function ListItem({ text }) {
return (
<li>{ text }</li>
);
}
then your loop will be changed as
const list = tasks.map((t, index) =>
<ListItem key={index} text={t}>
);
In this case, you place the key
on ListItem
and the key
will be associated with the element you added it on and all the elements nested inside ListItem
.
Please note that in above examples, i have used index
as key
. You should only use index
as key
if you don't have any other unique value to use as key.
Upvotes: 1
Reputation: 1814
“Props" is a special keyword in React, which stands for properties and is being used for passing data from one component to another. But the important part here is that data with props are being passed in a uni-directional flow. (one way from parent to child) Furthermore, props data is read-only, which means that data coming from the parent should not be changed by child components.
So if you have to access the first element, then you can access like below props.users[0] - > Gives the first element in the JSON array and props.users[1] so on
props.users[0]
{
"login": "mojombo",
"id": 17,
"avatar_url": "https://avatars0.githubusercontent.com/u/1?v=4",
"url": "https://api.github.com/users/mojombo",
"html_url": "https://github.com/mojombo"
}
Now,
1 const Users = (props) => {
2 //class changed to arrow functions
3 if (props.loading) {
4 return <Spinner />
5 }
6 else {
7 return (
8 <div className="row">
9 {props.users.map((user,index) => ( --> Change here
10 <div className="col-sm-3 mt-3" >
11 <UserItem
key={index} --> Change here
user={user}
/>
12 </div>
13 ))}
14 </div >
15 );
16 }
17 }
Since, map funtion will iterate your whole array, so when redering it to return some view you have to give some uniqueness column or value to key variable so that react will know the number of different divs to render.
References : https://itnext.io/what-is-props-and-how-to-use-it-in-react-da307f500da0
Upvotes: 0
Reputation: 9084
Change,
{props.users.map((user) => (
<div className="col-sm-3 mt-3" >
<UserItem key={user.id} user={user} />
</div>
))}
To
{props.users.map((user) => (
<div className="col-sm-3 mt-3" key={user.id}>
<UserItem user={user} />
</div>
))}
Here the key={user.id}
needs to be in div
element which is the immediate parent element of map
method..
-> The key prop has to be in the parent element under
map
method which refers to all the sibilings..-> Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity and it needs to be in immediate parent element.
-> The outermost/parent element returned by the map function needs to have a key prop with unique value.
Here in your code,
Parent Element:
<div className="col-sm-3 mt-3" key={user.id}>
has the sibiling,
<UserItem key={user.id} user={user} />
So parent element needs to identified with unique value in key prop..
Upvotes: 1
Reputation: 467
<UserItem key={user.id} user={user} />
implies that you are passing the key
as props to the child element UserItem
.
But what you actually did by providing key to div
is correct.
Assuming {user.id}
is unique for each user , using that on your div <div key={user.id} className="col-sm-3 mt-3" >
ensures that your div always have a unique key when the list is looped..
Upvotes: 0