I am using React, my state is defined as an array of object. I need to be able to change only one specific element in the state.data array, example object with id 1.
I would like to know:
- what is the proper way how to use
setState()
in this scenario.
constructor(props) {
super(props);
this.state = {
data: [{
id: 0,
title: 'Buy a',
status: 0, // 0 = todo, 1 = done
},
{
id: 1,
title: 'Buy b',
status: 0,
},
{
id: 2,
title: 'Buy c',
status: 0,
}
]
};
this.onTitleChange = this.onTitleChange.bind(this);
}
onTitleChange(id, title) {
console.log(id, title);
debugger
}
I am using React, my state is defined as an array of object. I need to be able to change only one specific element in the state.data array, example object with id 1.
I would like to know:
- what is the proper way how to use
setState()
in this scenario.
constructor(props) {
super(props);
this.state = {
data: [{
id: 0,
title: 'Buy a',
status: 0, // 0 = todo, 1 = done
},
{
id: 1,
title: 'Buy b',
status: 0,
},
{
id: 2,
title: 'Buy c',
status: 0,
}
]
};
this.onTitleChange = this.onTitleChange.bind(this);
}
onTitleChange(id, title) {
console.log(id, title);
debugger
}
Share
Improve this question
edited Nov 14, 2017 at 10:45
Shubham Khatri
282k58 gold badges429 silver badges411 bronze badges
asked Aug 25, 2017 at 9:14
RadexRadex
8,57724 gold badges60 silver badges96 bronze badges
5 Answers
Reset to default 17You can get do a cloning of the state object using spread operator and then find the index of object in array with a given id using findIndex
method Modify the object and set the state.
constructor(props) {
super(props);
this.state = {
data: [{
id: 0,
title: 'Buy a',
status: 0, // 0 = todo, 1 = done
},
{
id: 1,
title: 'Buy b',
status: 0,
},
{
id: 2,
title: 'Buy c',
status: 0,
}
]
};
this.onTitleChange = this.onTitleChange.bind(this);
}
onTitleChange(id, title) {
var data = [...this.state.data];
var index = data.findIndex(obj => obj.id === id);
data[index].title = title;
this.setState({data});
}
You can also modify the way you are
storing the state in the below format
for ease, hope this helps!
constructor(props) {
super(props);
this.state = {
data: [
0: {
id: 0,
title: 'Buy a',
status: 0, // 0 = todo, 1 = done
},
1: {
id: 1,
title: 'Buy b',
status: 0,
},
2: {
id: 2,
title: 'Buy c',
status: 0,
}
]
};
this.onTitleChange = this.onTitleChange.bind(this);
}
onTitleChange(id, title) {
var newData = [...this.state.data];
newData[id].title = title;
this.setState({newData});
}
You could also do something like this:
onChange = (id, value, field) => {
this.setState((prevState) => ({
data: prevState.data.map((d, index) => { //d = object, index = index in array
if (d.id === id) {
return {
...d,
[field]: value //field/name in object
}
}
return d
})
}), () => {
console.log("New value of", field, "=", value, "in object with id", id);
});
}
A simple solution would be:
const idx = this.state.data.findIndex(obj => obj === id);
this.state.data[idx].title = title;
For more complex component, I would recommend to use Immutable.js List
I would use the spread operator to update the state.
onTitleChange(id, title) {
const { data } = this.state
const index = data.findIndex(d => d.id === id)
this.setState({
data: [
...data.slice(0, index),
{
...data[index],
title: title,
},
...data.slice(index + 1)
]
})
}