Updating an object with setState in React
There are multiple ways of doing this, since state update is a async operation, so to update the state object, we need to use updater function with setState
.
1- Simplest one:
First create a copy of jasper
then do the changes in that:
this.setState(prevState => { let jasper = Object.assign({}, prevState.jasper); // creating copy of state variable jasper jasper.name = 'someothername'; // update the name property, assign a new value return { jasper }; // return new object jasper object})
Instead of using Object.assign
we can also write it like this:
let jasper = { ...prevState.jasper };
2- Using spread syntax:
this.setState(prevState => ({ jasper: { // object that we want to update ...prevState.jasper, // keep all other key-value pairs name: 'something' // update the value of specific key }}))
Note: Object.assign
and Spread Operator
creates only shallow copy, so if you have defined nested object or array of objects, you need a different approach.
Updating nested state object:
Assume you have defined state as:
this.state = { food: { sandwich: { capsicum: true, crackers: true, mayonnaise: true }, pizza: { jalapeno: true, extraCheese: false } }}
To update extraCheese of pizza object:
this.setState(prevState => ({ food: { ...prevState.food, // copy all other key-value pairs of food object pizza: { // specific object of food object ...prevState.food.pizza, // copy all pizza key-value pairs extraCheese: true // update value of specific key } }}))
Updating array of objects:
Lets assume you have a todo app, and you are managing the data in this form:
this.state = { todoItems: [ { name: 'Learn React Basics', status: 'pending' }, { name: 'Check Codebase', status: 'pending' } ]}
To update the status of any todo object, run a map on the array and check for some unique value of each object, in case of condition=true
, return the new object with updated value, else same object.
let key = 2;this.setState(prevState => ({ todoItems: prevState.todoItems.map( el => el.key === key? { ...el, status: 'done' }: el )}))
Suggestion: If object doesn't have a unique value, then use array index.