How to create unique keys for React elements?
up vote
17
down vote
favorite
I am making a React app that allows you to make a list and save it, but React has been giving me a warning that my elements don't have a unique key prop (elements List/ListForm). How should I create a unique key prop for user created elements? Below is my React code
var TitleForm = React.createClass({
handleSubmit: function(e) {
e.preventDefault();
var listName = {'name':this.refs.listName.value};
this.props.handleCreate(listName);
this.refs.listName.value = "";
},
render: function() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input className='form-control list-input' type='text' ref='listName' placeholder="List Name"/>
<br/>
<button className="btn btn-primary" type="submit">Create</button>
</form>
</div>
);
}
});
var ListForm = React.createClass({
getInitialState: function() {
return {items:[{'name':'item1'}],itemCount:1};
},
handleSubmit: function(e) {
e.preventDefault();
var list = {'name': this.props.name, 'data':};
var items = this.state.items;
for (var i = 1; i < items.length; i++) {
list.data.push(this.refs[items[i].name]);
}
this.props.update(list);
$('#'+this.props.name).remove();
},
handleClick: function() {
this.setState({
items: this.state.items.concat({'name':'item'+this.state.itemCount+1}),
itemCount: this.state.itemCount+1
});
},
handleDelete: function() {
this.setState({
itemCount: this.state.itemCount-1
});
},
render: function() {
var listItems = this.state.items.map(function(item) {
return (
<div>
<input type="text" className="list-form" placeholder="List Item" ref={item.name}/>
<br/>
</div>
);
});
return (
<div>
<form onSubmit={this.handleSubmit} className="well list-form-container">
{listItems}
<br/>
<div onClick={this.handleClick} className="btn btn-primary list-button">Add</div>
<div onClick={this.handleDelete} className="btn btn-primary list-button">Delete</div>
<button type="submit" className="btn btn-primary list-button">Save</button>
</form>
</div>
)
}
});
var List = React.createClass({
getInitialState: function() {
return {lists:, savedLists: };
},
handleCreate: function(listName) {
this.setState({
lists: this.state.lists.concat(listName)
});
},
updateSaved: function(list) {
this.setState({
savedLists: this.state.savedLists.concat(list)
});
},
render: function() {
var lst = this;
var lists = this.state.lists.map(function(list) {
return(
<div>
<div key={list.name} id={list.name}>
<h2 key={"header"+list.name}>{list.name}</h2>
<ListForm update={lst.updateSaved} name={list.name}/>
</div>
</div>
)
});
var savedLists = this.state.savedLists.map(function(list) {
var list_data = list.data;
list_data.map(function(data) {
return (
<li>{data}</li>
)
});
return(
<div>
<h2>{list.name}</h2>
<ul>
{list_data}
</ul>
</div>
)
});
var save_msg;
if(savedLists.length == 0){
save_msg = 'No Saved Lists';
}else{
save_msg = 'Saved Lists';
}
return (
<div>
<TitleForm handleCreate={this.handleCreate} />
{lists}
<h2>{save_msg}</h2>
{savedLists}
</div>
)
}
});
ReactDOM.render(<List/>,document.getElementById('app'));
My HTML:
<div class="container">
<h1>Title</h1>
<div id="app" class="center"></div>
</div>
reactjs
add a comment |
up vote
17
down vote
favorite
I am making a React app that allows you to make a list and save it, but React has been giving me a warning that my elements don't have a unique key prop (elements List/ListForm). How should I create a unique key prop for user created elements? Below is my React code
var TitleForm = React.createClass({
handleSubmit: function(e) {
e.preventDefault();
var listName = {'name':this.refs.listName.value};
this.props.handleCreate(listName);
this.refs.listName.value = "";
},
render: function() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input className='form-control list-input' type='text' ref='listName' placeholder="List Name"/>
<br/>
<button className="btn btn-primary" type="submit">Create</button>
</form>
</div>
);
}
});
var ListForm = React.createClass({
getInitialState: function() {
return {items:[{'name':'item1'}],itemCount:1};
},
handleSubmit: function(e) {
e.preventDefault();
var list = {'name': this.props.name, 'data':};
var items = this.state.items;
for (var i = 1; i < items.length; i++) {
list.data.push(this.refs[items[i].name]);
}
this.props.update(list);
$('#'+this.props.name).remove();
},
handleClick: function() {
this.setState({
items: this.state.items.concat({'name':'item'+this.state.itemCount+1}),
itemCount: this.state.itemCount+1
});
},
handleDelete: function() {
this.setState({
itemCount: this.state.itemCount-1
});
},
render: function() {
var listItems = this.state.items.map(function(item) {
return (
<div>
<input type="text" className="list-form" placeholder="List Item" ref={item.name}/>
<br/>
</div>
);
});
return (
<div>
<form onSubmit={this.handleSubmit} className="well list-form-container">
{listItems}
<br/>
<div onClick={this.handleClick} className="btn btn-primary list-button">Add</div>
<div onClick={this.handleDelete} className="btn btn-primary list-button">Delete</div>
<button type="submit" className="btn btn-primary list-button">Save</button>
</form>
</div>
)
}
});
var List = React.createClass({
getInitialState: function() {
return {lists:, savedLists: };
},
handleCreate: function(listName) {
this.setState({
lists: this.state.lists.concat(listName)
});
},
updateSaved: function(list) {
this.setState({
savedLists: this.state.savedLists.concat(list)
});
},
render: function() {
var lst = this;
var lists = this.state.lists.map(function(list) {
return(
<div>
<div key={list.name} id={list.name}>
<h2 key={"header"+list.name}>{list.name}</h2>
<ListForm update={lst.updateSaved} name={list.name}/>
</div>
</div>
)
});
var savedLists = this.state.savedLists.map(function(list) {
var list_data = list.data;
list_data.map(function(data) {
return (
<li>{data}</li>
)
});
return(
<div>
<h2>{list.name}</h2>
<ul>
{list_data}
</ul>
</div>
)
});
var save_msg;
if(savedLists.length == 0){
save_msg = 'No Saved Lists';
}else{
save_msg = 'Saved Lists';
}
return (
<div>
<TitleForm handleCreate={this.handleCreate} />
{lists}
<h2>{save_msg}</h2>
{savedLists}
</div>
)
}
});
ReactDOM.render(<List/>,document.getElementById('app'));
My HTML:
<div class="container">
<h1>Title</h1>
<div id="app" class="center"></div>
</div>
reactjs
1
You can useuuid
npm package. npmjs.com/package/uuid
– RIYAJ KHAN
Nov 13 '17 at 6:34
@RIYAJKHAN - If you use this package can you make one global version of const uuidv4 = require('uuid/v4'); or should you have one per component?
– chobo2
Jul 18 at 19:53
@chobo2 there is nothing like . global or local to component.You can import and use it
– RIYAJ KHAN
Jul 19 at 3:18
@RIYAJKHAN - I meant should I put it in it's own file and then export it into other components? But it sounds like there is no point doing that.
– chobo2
Jul 19 at 16:19
no need to export in other component,Just import in the component where you want to use it
– RIYAJ KHAN
Jul 19 at 17:06
add a comment |
up vote
17
down vote
favorite
up vote
17
down vote
favorite
I am making a React app that allows you to make a list and save it, but React has been giving me a warning that my elements don't have a unique key prop (elements List/ListForm). How should I create a unique key prop for user created elements? Below is my React code
var TitleForm = React.createClass({
handleSubmit: function(e) {
e.preventDefault();
var listName = {'name':this.refs.listName.value};
this.props.handleCreate(listName);
this.refs.listName.value = "";
},
render: function() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input className='form-control list-input' type='text' ref='listName' placeholder="List Name"/>
<br/>
<button className="btn btn-primary" type="submit">Create</button>
</form>
</div>
);
}
});
var ListForm = React.createClass({
getInitialState: function() {
return {items:[{'name':'item1'}],itemCount:1};
},
handleSubmit: function(e) {
e.preventDefault();
var list = {'name': this.props.name, 'data':};
var items = this.state.items;
for (var i = 1; i < items.length; i++) {
list.data.push(this.refs[items[i].name]);
}
this.props.update(list);
$('#'+this.props.name).remove();
},
handleClick: function() {
this.setState({
items: this.state.items.concat({'name':'item'+this.state.itemCount+1}),
itemCount: this.state.itemCount+1
});
},
handleDelete: function() {
this.setState({
itemCount: this.state.itemCount-1
});
},
render: function() {
var listItems = this.state.items.map(function(item) {
return (
<div>
<input type="text" className="list-form" placeholder="List Item" ref={item.name}/>
<br/>
</div>
);
});
return (
<div>
<form onSubmit={this.handleSubmit} className="well list-form-container">
{listItems}
<br/>
<div onClick={this.handleClick} className="btn btn-primary list-button">Add</div>
<div onClick={this.handleDelete} className="btn btn-primary list-button">Delete</div>
<button type="submit" className="btn btn-primary list-button">Save</button>
</form>
</div>
)
}
});
var List = React.createClass({
getInitialState: function() {
return {lists:, savedLists: };
},
handleCreate: function(listName) {
this.setState({
lists: this.state.lists.concat(listName)
});
},
updateSaved: function(list) {
this.setState({
savedLists: this.state.savedLists.concat(list)
});
},
render: function() {
var lst = this;
var lists = this.state.lists.map(function(list) {
return(
<div>
<div key={list.name} id={list.name}>
<h2 key={"header"+list.name}>{list.name}</h2>
<ListForm update={lst.updateSaved} name={list.name}/>
</div>
</div>
)
});
var savedLists = this.state.savedLists.map(function(list) {
var list_data = list.data;
list_data.map(function(data) {
return (
<li>{data}</li>
)
});
return(
<div>
<h2>{list.name}</h2>
<ul>
{list_data}
</ul>
</div>
)
});
var save_msg;
if(savedLists.length == 0){
save_msg = 'No Saved Lists';
}else{
save_msg = 'Saved Lists';
}
return (
<div>
<TitleForm handleCreate={this.handleCreate} />
{lists}
<h2>{save_msg}</h2>
{savedLists}
</div>
)
}
});
ReactDOM.render(<List/>,document.getElementById('app'));
My HTML:
<div class="container">
<h1>Title</h1>
<div id="app" class="center"></div>
</div>
reactjs
I am making a React app that allows you to make a list and save it, but React has been giving me a warning that my elements don't have a unique key prop (elements List/ListForm). How should I create a unique key prop for user created elements? Below is my React code
var TitleForm = React.createClass({
handleSubmit: function(e) {
e.preventDefault();
var listName = {'name':this.refs.listName.value};
this.props.handleCreate(listName);
this.refs.listName.value = "";
},
render: function() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input className='form-control list-input' type='text' ref='listName' placeholder="List Name"/>
<br/>
<button className="btn btn-primary" type="submit">Create</button>
</form>
</div>
);
}
});
var ListForm = React.createClass({
getInitialState: function() {
return {items:[{'name':'item1'}],itemCount:1};
},
handleSubmit: function(e) {
e.preventDefault();
var list = {'name': this.props.name, 'data':};
var items = this.state.items;
for (var i = 1; i < items.length; i++) {
list.data.push(this.refs[items[i].name]);
}
this.props.update(list);
$('#'+this.props.name).remove();
},
handleClick: function() {
this.setState({
items: this.state.items.concat({'name':'item'+this.state.itemCount+1}),
itemCount: this.state.itemCount+1
});
},
handleDelete: function() {
this.setState({
itemCount: this.state.itemCount-1
});
},
render: function() {
var listItems = this.state.items.map(function(item) {
return (
<div>
<input type="text" className="list-form" placeholder="List Item" ref={item.name}/>
<br/>
</div>
);
});
return (
<div>
<form onSubmit={this.handleSubmit} className="well list-form-container">
{listItems}
<br/>
<div onClick={this.handleClick} className="btn btn-primary list-button">Add</div>
<div onClick={this.handleDelete} className="btn btn-primary list-button">Delete</div>
<button type="submit" className="btn btn-primary list-button">Save</button>
</form>
</div>
)
}
});
var List = React.createClass({
getInitialState: function() {
return {lists:, savedLists: };
},
handleCreate: function(listName) {
this.setState({
lists: this.state.lists.concat(listName)
});
},
updateSaved: function(list) {
this.setState({
savedLists: this.state.savedLists.concat(list)
});
},
render: function() {
var lst = this;
var lists = this.state.lists.map(function(list) {
return(
<div>
<div key={list.name} id={list.name}>
<h2 key={"header"+list.name}>{list.name}</h2>
<ListForm update={lst.updateSaved} name={list.name}/>
</div>
</div>
)
});
var savedLists = this.state.savedLists.map(function(list) {
var list_data = list.data;
list_data.map(function(data) {
return (
<li>{data}</li>
)
});
return(
<div>
<h2>{list.name}</h2>
<ul>
{list_data}
</ul>
</div>
)
});
var save_msg;
if(savedLists.length == 0){
save_msg = 'No Saved Lists';
}else{
save_msg = 'Saved Lists';
}
return (
<div>
<TitleForm handleCreate={this.handleCreate} />
{lists}
<h2>{save_msg}</h2>
{savedLists}
</div>
)
}
});
ReactDOM.render(<List/>,document.getElementById('app'));
My HTML:
<div class="container">
<h1>Title</h1>
<div id="app" class="center"></div>
</div>
reactjs
reactjs
asked Sep 17 '16 at 16:57
user1775500
3642514
3642514
1
You can useuuid
npm package. npmjs.com/package/uuid
– RIYAJ KHAN
Nov 13 '17 at 6:34
@RIYAJKHAN - If you use this package can you make one global version of const uuidv4 = require('uuid/v4'); or should you have one per component?
– chobo2
Jul 18 at 19:53
@chobo2 there is nothing like . global or local to component.You can import and use it
– RIYAJ KHAN
Jul 19 at 3:18
@RIYAJKHAN - I meant should I put it in it's own file and then export it into other components? But it sounds like there is no point doing that.
– chobo2
Jul 19 at 16:19
no need to export in other component,Just import in the component where you want to use it
– RIYAJ KHAN
Jul 19 at 17:06
add a comment |
1
You can useuuid
npm package. npmjs.com/package/uuid
– RIYAJ KHAN
Nov 13 '17 at 6:34
@RIYAJKHAN - If you use this package can you make one global version of const uuidv4 = require('uuid/v4'); or should you have one per component?
– chobo2
Jul 18 at 19:53
@chobo2 there is nothing like . global or local to component.You can import and use it
– RIYAJ KHAN
Jul 19 at 3:18
@RIYAJKHAN - I meant should I put it in it's own file and then export it into other components? But it sounds like there is no point doing that.
– chobo2
Jul 19 at 16:19
no need to export in other component,Just import in the component where you want to use it
– RIYAJ KHAN
Jul 19 at 17:06
1
1
You can use
uuid
npm package. npmjs.com/package/uuid– RIYAJ KHAN
Nov 13 '17 at 6:34
You can use
uuid
npm package. npmjs.com/package/uuid– RIYAJ KHAN
Nov 13 '17 at 6:34
@RIYAJKHAN - If you use this package can you make one global version of const uuidv4 = require('uuid/v4'); or should you have one per component?
– chobo2
Jul 18 at 19:53
@RIYAJKHAN - If you use this package can you make one global version of const uuidv4 = require('uuid/v4'); or should you have one per component?
– chobo2
Jul 18 at 19:53
@chobo2 there is nothing like . global or local to component.You can import and use it
– RIYAJ KHAN
Jul 19 at 3:18
@chobo2 there is nothing like . global or local to component.You can import and use it
– RIYAJ KHAN
Jul 19 at 3:18
@RIYAJKHAN - I meant should I put it in it's own file and then export it into other components? But it sounds like there is no point doing that.
– chobo2
Jul 19 at 16:19
@RIYAJKHAN - I meant should I put it in it's own file and then export it into other components? But it sounds like there is no point doing that.
– chobo2
Jul 19 at 16:19
no need to export in other component,Just import in the component where you want to use it
– RIYAJ KHAN
Jul 19 at 17:06
no need to export in other component,Just import in the component where you want to use it
– RIYAJ KHAN
Jul 19 at 17:06
add a comment |
5 Answers
5
active
oldest
votes
up vote
20
down vote
accepted
There are many ways in which you can create unique keys
, the simplest method is to use the index when iterating arrays.
Example
var lists = this.state.lists.map(function(list, index) {
return(
<div key={index}>
<div key={list.name} id={list.name}>
<h2 key={"header"+list.name}>{list.name}</h2>
<ListForm update={lst.updateSaved} name={list.name}/>
</div>
</div>
)
});
Wherever you're lopping over data, here this.state.lists.map
, you can pass second parameter function(list, index)
to the callback as well and that will be its index
value and it will be unique for all the items in the array.
And then you can use it like
<div key={index}>
You can do the same here as well
var savedLists = this.state.savedLists.map(function(list, index) {
var list_data = list.data;
list_data.map(function(data, index) {
return (
<li key={index}>{data}</li>
)
});
return(
<div key={index}>
<h2>{list.name}</h2>
<ul>
{list_data}
</ul>
</div>
)
});
Edit
However, As pointed by the user Martin Dawson in the comment below, This is not always ideal.
So whats the solution then?
Many
- You can create a function to generate unique keys/ids/numbers/strings and use that
- You can make use of existing npm packages like uuid, uniqid, etc
- You can also generate random number like
new Date().getTime();
and prefix it with something from the item you're iterating to guarantee its uniqueness - Lastly, I recommend using the unique ID you get from the database, If you get it.
Example:
const generateKey = (pre) => {
return `${ pre }_${ new Date().getTime() }`;
}
const savedLists = this.state.savedLists.map( list => {
const list_data = list.data.map( data => <li key={ generateKey(data) }>{ data }</li> );
return(
<div key={ generateKey(list.name) }>
<h2>{ list.name }</h2>
<ul>
{ list_data }
</ul>
</div>
)
});
24
This is fine if the elements do not get removed or added to them but if they do then you will have weird side-effects as React will associate the keys with wrong components
– Martin Dawson
Oct 10 '16 at 18:58
True., I am sure users can download other libs or create helper functions to take care of this., I will update the answer in regards to this.
– Random User
Sep 1 '17 at 6:25
Just check out this article: codeburst.io/…
– Karlen Kishmiryan
Apr 10 at 10:34
add a comment |
up vote
7
down vote
One can use uuid
npm package for it.
Nodejs common module
const uuidv1 = require('uuid/v1');
uuidv1(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
With ecma6:
import uuidv1 from 'uuid/v1';
uuidv1(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
Dont ever use dynamically generated ID's for React keys. That defeats the purpose of the key management if the component is dynamically rendered, because it breaks the whole tree.
– Frondor
Dec 6 at 13:06
add a comment |
up vote
1
down vote
Updating the answer with v4 of UUID
npm install uuid
-------------------------------------
const uuidv4 = require('uuid/v4');
uuidv4(); // ⇨ '10ba038e-48da-487b-96e8-8d3b99b6d18a'
or
import uuidv from 'uuid/v4';
uuidv4(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
add a comment |
up vote
1
down vote
As mentioned before, using index is an antipattern. The best option I've found so far is:
1) Import "shortid" from React library:
import shortid from 'shortid';
2) Use it in your loop like bellow:
const controls = ;
collection.map(item => {
controls.push(<div className="column" key={`div-${shortid.generate()}`}>{item.text}</div>);
});
Hope this helps. I just posted this because it was really hard to find a solution like this.
Documentation for React Keys: reactjs.org/docs/lists-and-keys.html#keys Also, don't forget to run "npm install shortid --save"
– Daniel Santana
Nov 14 at 22:59
add a comment |
up vote
-4
down vote
I am using this:
<div key={+new Date() + Math.random()}>
this will not work as the keys are determined at time of render, therefore not deterministic.
– steviejay
Oct 13 at 4:15
add a comment |
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
20
down vote
accepted
There are many ways in which you can create unique keys
, the simplest method is to use the index when iterating arrays.
Example
var lists = this.state.lists.map(function(list, index) {
return(
<div key={index}>
<div key={list.name} id={list.name}>
<h2 key={"header"+list.name}>{list.name}</h2>
<ListForm update={lst.updateSaved} name={list.name}/>
</div>
</div>
)
});
Wherever you're lopping over data, here this.state.lists.map
, you can pass second parameter function(list, index)
to the callback as well and that will be its index
value and it will be unique for all the items in the array.
And then you can use it like
<div key={index}>
You can do the same here as well
var savedLists = this.state.savedLists.map(function(list, index) {
var list_data = list.data;
list_data.map(function(data, index) {
return (
<li key={index}>{data}</li>
)
});
return(
<div key={index}>
<h2>{list.name}</h2>
<ul>
{list_data}
</ul>
</div>
)
});
Edit
However, As pointed by the user Martin Dawson in the comment below, This is not always ideal.
So whats the solution then?
Many
- You can create a function to generate unique keys/ids/numbers/strings and use that
- You can make use of existing npm packages like uuid, uniqid, etc
- You can also generate random number like
new Date().getTime();
and prefix it with something from the item you're iterating to guarantee its uniqueness - Lastly, I recommend using the unique ID you get from the database, If you get it.
Example:
const generateKey = (pre) => {
return `${ pre }_${ new Date().getTime() }`;
}
const savedLists = this.state.savedLists.map( list => {
const list_data = list.data.map( data => <li key={ generateKey(data) }>{ data }</li> );
return(
<div key={ generateKey(list.name) }>
<h2>{ list.name }</h2>
<ul>
{ list_data }
</ul>
</div>
)
});
24
This is fine if the elements do not get removed or added to them but if they do then you will have weird side-effects as React will associate the keys with wrong components
– Martin Dawson
Oct 10 '16 at 18:58
True., I am sure users can download other libs or create helper functions to take care of this., I will update the answer in regards to this.
– Random User
Sep 1 '17 at 6:25
Just check out this article: codeburst.io/…
– Karlen Kishmiryan
Apr 10 at 10:34
add a comment |
up vote
20
down vote
accepted
There are many ways in which you can create unique keys
, the simplest method is to use the index when iterating arrays.
Example
var lists = this.state.lists.map(function(list, index) {
return(
<div key={index}>
<div key={list.name} id={list.name}>
<h2 key={"header"+list.name}>{list.name}</h2>
<ListForm update={lst.updateSaved} name={list.name}/>
</div>
</div>
)
});
Wherever you're lopping over data, here this.state.lists.map
, you can pass second parameter function(list, index)
to the callback as well and that will be its index
value and it will be unique for all the items in the array.
And then you can use it like
<div key={index}>
You can do the same here as well
var savedLists = this.state.savedLists.map(function(list, index) {
var list_data = list.data;
list_data.map(function(data, index) {
return (
<li key={index}>{data}</li>
)
});
return(
<div key={index}>
<h2>{list.name}</h2>
<ul>
{list_data}
</ul>
</div>
)
});
Edit
However, As pointed by the user Martin Dawson in the comment below, This is not always ideal.
So whats the solution then?
Many
- You can create a function to generate unique keys/ids/numbers/strings and use that
- You can make use of existing npm packages like uuid, uniqid, etc
- You can also generate random number like
new Date().getTime();
and prefix it with something from the item you're iterating to guarantee its uniqueness - Lastly, I recommend using the unique ID you get from the database, If you get it.
Example:
const generateKey = (pre) => {
return `${ pre }_${ new Date().getTime() }`;
}
const savedLists = this.state.savedLists.map( list => {
const list_data = list.data.map( data => <li key={ generateKey(data) }>{ data }</li> );
return(
<div key={ generateKey(list.name) }>
<h2>{ list.name }</h2>
<ul>
{ list_data }
</ul>
</div>
)
});
24
This is fine if the elements do not get removed or added to them but if they do then you will have weird side-effects as React will associate the keys with wrong components
– Martin Dawson
Oct 10 '16 at 18:58
True., I am sure users can download other libs or create helper functions to take care of this., I will update the answer in regards to this.
– Random User
Sep 1 '17 at 6:25
Just check out this article: codeburst.io/…
– Karlen Kishmiryan
Apr 10 at 10:34
add a comment |
up vote
20
down vote
accepted
up vote
20
down vote
accepted
There are many ways in which you can create unique keys
, the simplest method is to use the index when iterating arrays.
Example
var lists = this.state.lists.map(function(list, index) {
return(
<div key={index}>
<div key={list.name} id={list.name}>
<h2 key={"header"+list.name}>{list.name}</h2>
<ListForm update={lst.updateSaved} name={list.name}/>
</div>
</div>
)
});
Wherever you're lopping over data, here this.state.lists.map
, you can pass second parameter function(list, index)
to the callback as well and that will be its index
value and it will be unique for all the items in the array.
And then you can use it like
<div key={index}>
You can do the same here as well
var savedLists = this.state.savedLists.map(function(list, index) {
var list_data = list.data;
list_data.map(function(data, index) {
return (
<li key={index}>{data}</li>
)
});
return(
<div key={index}>
<h2>{list.name}</h2>
<ul>
{list_data}
</ul>
</div>
)
});
Edit
However, As pointed by the user Martin Dawson in the comment below, This is not always ideal.
So whats the solution then?
Many
- You can create a function to generate unique keys/ids/numbers/strings and use that
- You can make use of existing npm packages like uuid, uniqid, etc
- You can also generate random number like
new Date().getTime();
and prefix it with something from the item you're iterating to guarantee its uniqueness - Lastly, I recommend using the unique ID you get from the database, If you get it.
Example:
const generateKey = (pre) => {
return `${ pre }_${ new Date().getTime() }`;
}
const savedLists = this.state.savedLists.map( list => {
const list_data = list.data.map( data => <li key={ generateKey(data) }>{ data }</li> );
return(
<div key={ generateKey(list.name) }>
<h2>{ list.name }</h2>
<ul>
{ list_data }
</ul>
</div>
)
});
There are many ways in which you can create unique keys
, the simplest method is to use the index when iterating arrays.
Example
var lists = this.state.lists.map(function(list, index) {
return(
<div key={index}>
<div key={list.name} id={list.name}>
<h2 key={"header"+list.name}>{list.name}</h2>
<ListForm update={lst.updateSaved} name={list.name}/>
</div>
</div>
)
});
Wherever you're lopping over data, here this.state.lists.map
, you can pass second parameter function(list, index)
to the callback as well and that will be its index
value and it will be unique for all the items in the array.
And then you can use it like
<div key={index}>
You can do the same here as well
var savedLists = this.state.savedLists.map(function(list, index) {
var list_data = list.data;
list_data.map(function(data, index) {
return (
<li key={index}>{data}</li>
)
});
return(
<div key={index}>
<h2>{list.name}</h2>
<ul>
{list_data}
</ul>
</div>
)
});
Edit
However, As pointed by the user Martin Dawson in the comment below, This is not always ideal.
So whats the solution then?
Many
- You can create a function to generate unique keys/ids/numbers/strings and use that
- You can make use of existing npm packages like uuid, uniqid, etc
- You can also generate random number like
new Date().getTime();
and prefix it with something from the item you're iterating to guarantee its uniqueness - Lastly, I recommend using the unique ID you get from the database, If you get it.
Example:
const generateKey = (pre) => {
return `${ pre }_${ new Date().getTime() }`;
}
const savedLists = this.state.savedLists.map( list => {
const list_data = list.data.map( data => <li key={ generateKey(data) }>{ data }</li> );
return(
<div key={ generateKey(list.name) }>
<h2>{ list.name }</h2>
<ul>
{ list_data }
</ul>
</div>
)
});
edited Nov 13 '17 at 6:16
answered Sep 17 '16 at 17:04
Random User
3,10462741
3,10462741
24
This is fine if the elements do not get removed or added to them but if they do then you will have weird side-effects as React will associate the keys with wrong components
– Martin Dawson
Oct 10 '16 at 18:58
True., I am sure users can download other libs or create helper functions to take care of this., I will update the answer in regards to this.
– Random User
Sep 1 '17 at 6:25
Just check out this article: codeburst.io/…
– Karlen Kishmiryan
Apr 10 at 10:34
add a comment |
24
This is fine if the elements do not get removed or added to them but if they do then you will have weird side-effects as React will associate the keys with wrong components
– Martin Dawson
Oct 10 '16 at 18:58
True., I am sure users can download other libs or create helper functions to take care of this., I will update the answer in regards to this.
– Random User
Sep 1 '17 at 6:25
Just check out this article: codeburst.io/…
– Karlen Kishmiryan
Apr 10 at 10:34
24
24
This is fine if the elements do not get removed or added to them but if they do then you will have weird side-effects as React will associate the keys with wrong components
– Martin Dawson
Oct 10 '16 at 18:58
This is fine if the elements do not get removed or added to them but if they do then you will have weird side-effects as React will associate the keys with wrong components
– Martin Dawson
Oct 10 '16 at 18:58
True., I am sure users can download other libs or create helper functions to take care of this., I will update the answer in regards to this.
– Random User
Sep 1 '17 at 6:25
True., I am sure users can download other libs or create helper functions to take care of this., I will update the answer in regards to this.
– Random User
Sep 1 '17 at 6:25
Just check out this article: codeburst.io/…
– Karlen Kishmiryan
Apr 10 at 10:34
Just check out this article: codeburst.io/…
– Karlen Kishmiryan
Apr 10 at 10:34
add a comment |
up vote
7
down vote
One can use uuid
npm package for it.
Nodejs common module
const uuidv1 = require('uuid/v1');
uuidv1(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
With ecma6:
import uuidv1 from 'uuid/v1';
uuidv1(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
Dont ever use dynamically generated ID's for React keys. That defeats the purpose of the key management if the component is dynamically rendered, because it breaks the whole tree.
– Frondor
Dec 6 at 13:06
add a comment |
up vote
7
down vote
One can use uuid
npm package for it.
Nodejs common module
const uuidv1 = require('uuid/v1');
uuidv1(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
With ecma6:
import uuidv1 from 'uuid/v1';
uuidv1(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
Dont ever use dynamically generated ID's for React keys. That defeats the purpose of the key management if the component is dynamically rendered, because it breaks the whole tree.
– Frondor
Dec 6 at 13:06
add a comment |
up vote
7
down vote
up vote
7
down vote
One can use uuid
npm package for it.
Nodejs common module
const uuidv1 = require('uuid/v1');
uuidv1(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
With ecma6:
import uuidv1 from 'uuid/v1';
uuidv1(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
One can use uuid
npm package for it.
Nodejs common module
const uuidv1 = require('uuid/v1');
uuidv1(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
With ecma6:
import uuidv1 from 'uuid/v1';
uuidv1(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
edited Oct 24 at 17:38
answered Jul 19 at 17:08
RIYAJ KHAN
10.6k41434
10.6k41434
Dont ever use dynamically generated ID's for React keys. That defeats the purpose of the key management if the component is dynamically rendered, because it breaks the whole tree.
– Frondor
Dec 6 at 13:06
add a comment |
Dont ever use dynamically generated ID's for React keys. That defeats the purpose of the key management if the component is dynamically rendered, because it breaks the whole tree.
– Frondor
Dec 6 at 13:06
Dont ever use dynamically generated ID's for React keys. That defeats the purpose of the key management if the component is dynamically rendered, because it breaks the whole tree.
– Frondor
Dec 6 at 13:06
Dont ever use dynamically generated ID's for React keys. That defeats the purpose of the key management if the component is dynamically rendered, because it breaks the whole tree.
– Frondor
Dec 6 at 13:06
add a comment |
up vote
1
down vote
Updating the answer with v4 of UUID
npm install uuid
-------------------------------------
const uuidv4 = require('uuid/v4');
uuidv4(); // ⇨ '10ba038e-48da-487b-96e8-8d3b99b6d18a'
or
import uuidv from 'uuid/v4';
uuidv4(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
add a comment |
up vote
1
down vote
Updating the answer with v4 of UUID
npm install uuid
-------------------------------------
const uuidv4 = require('uuid/v4');
uuidv4(); // ⇨ '10ba038e-48da-487b-96e8-8d3b99b6d18a'
or
import uuidv from 'uuid/v4';
uuidv4(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
add a comment |
up vote
1
down vote
up vote
1
down vote
Updating the answer with v4 of UUID
npm install uuid
-------------------------------------
const uuidv4 = require('uuid/v4');
uuidv4(); // ⇨ '10ba038e-48da-487b-96e8-8d3b99b6d18a'
or
import uuidv from 'uuid/v4';
uuidv4(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
Updating the answer with v4 of UUID
npm install uuid
-------------------------------------
const uuidv4 = require('uuid/v4');
uuidv4(); // ⇨ '10ba038e-48da-487b-96e8-8d3b99b6d18a'
or
import uuidv from 'uuid/v4';
uuidv4(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
answered Oct 24 at 18:24
Knitesh
1,2561016
1,2561016
add a comment |
add a comment |
up vote
1
down vote
As mentioned before, using index is an antipattern. The best option I've found so far is:
1) Import "shortid" from React library:
import shortid from 'shortid';
2) Use it in your loop like bellow:
const controls = ;
collection.map(item => {
controls.push(<div className="column" key={`div-${shortid.generate()}`}>{item.text}</div>);
});
Hope this helps. I just posted this because it was really hard to find a solution like this.
Documentation for React Keys: reactjs.org/docs/lists-and-keys.html#keys Also, don't forget to run "npm install shortid --save"
– Daniel Santana
Nov 14 at 22:59
add a comment |
up vote
1
down vote
As mentioned before, using index is an antipattern. The best option I've found so far is:
1) Import "shortid" from React library:
import shortid from 'shortid';
2) Use it in your loop like bellow:
const controls = ;
collection.map(item => {
controls.push(<div className="column" key={`div-${shortid.generate()}`}>{item.text}</div>);
});
Hope this helps. I just posted this because it was really hard to find a solution like this.
Documentation for React Keys: reactjs.org/docs/lists-and-keys.html#keys Also, don't forget to run "npm install shortid --save"
– Daniel Santana
Nov 14 at 22:59
add a comment |
up vote
1
down vote
up vote
1
down vote
As mentioned before, using index is an antipattern. The best option I've found so far is:
1) Import "shortid" from React library:
import shortid from 'shortid';
2) Use it in your loop like bellow:
const controls = ;
collection.map(item => {
controls.push(<div className="column" key={`div-${shortid.generate()}`}>{item.text}</div>);
});
Hope this helps. I just posted this because it was really hard to find a solution like this.
As mentioned before, using index is an antipattern. The best option I've found so far is:
1) Import "shortid" from React library:
import shortid from 'shortid';
2) Use it in your loop like bellow:
const controls = ;
collection.map(item => {
controls.push(<div className="column" key={`div-${shortid.generate()}`}>{item.text}</div>);
});
Hope this helps. I just posted this because it was really hard to find a solution like this.
answered Nov 14 at 22:52
Daniel Santana
83310
83310
Documentation for React Keys: reactjs.org/docs/lists-and-keys.html#keys Also, don't forget to run "npm install shortid --save"
– Daniel Santana
Nov 14 at 22:59
add a comment |
Documentation for React Keys: reactjs.org/docs/lists-and-keys.html#keys Also, don't forget to run "npm install shortid --save"
– Daniel Santana
Nov 14 at 22:59
Documentation for React Keys: reactjs.org/docs/lists-and-keys.html#keys Also, don't forget to run "npm install shortid --save"
– Daniel Santana
Nov 14 at 22:59
Documentation for React Keys: reactjs.org/docs/lists-and-keys.html#keys Also, don't forget to run "npm install shortid --save"
– Daniel Santana
Nov 14 at 22:59
add a comment |
up vote
-4
down vote
I am using this:
<div key={+new Date() + Math.random()}>
this will not work as the keys are determined at time of render, therefore not deterministic.
– steviejay
Oct 13 at 4:15
add a comment |
up vote
-4
down vote
I am using this:
<div key={+new Date() + Math.random()}>
this will not work as the keys are determined at time of render, therefore not deterministic.
– steviejay
Oct 13 at 4:15
add a comment |
up vote
-4
down vote
up vote
-4
down vote
I am using this:
<div key={+new Date() + Math.random()}>
I am using this:
<div key={+new Date() + Math.random()}>
answered Oct 11 at 13:13
Tudor Morar
1,430910
1,430910
this will not work as the keys are determined at time of render, therefore not deterministic.
– steviejay
Oct 13 at 4:15
add a comment |
this will not work as the keys are determined at time of render, therefore not deterministic.
– steviejay
Oct 13 at 4:15
this will not work as the keys are determined at time of render, therefore not deterministic.
– steviejay
Oct 13 at 4:15
this will not work as the keys are determined at time of render, therefore not deterministic.
– steviejay
Oct 13 at 4:15
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f39549424%2fhow-to-create-unique-keys-for-react-elements%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
You can use
uuid
npm package. npmjs.com/package/uuid– RIYAJ KHAN
Nov 13 '17 at 6:34
@RIYAJKHAN - If you use this package can you make one global version of const uuidv4 = require('uuid/v4'); or should you have one per component?
– chobo2
Jul 18 at 19:53
@chobo2 there is nothing like . global or local to component.You can import and use it
– RIYAJ KHAN
Jul 19 at 3:18
@RIYAJKHAN - I meant should I put it in it's own file and then export it into other components? But it sounds like there is no point doing that.
– chobo2
Jul 19 at 16:19
no need to export in other component,Just import in the component where you want to use it
– RIYAJ KHAN
Jul 19 at 17:06