updating an object with setstate in react

  • Last Update :
  • Techknowledgy :

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. Suggestion: If object doesn't have a unique value, then use array index. 1 I understand that React uses .assign() to. merge the old state object with the new object so shouldn't the second code work properly? – Saurabh Rana Feb 25, 2021 at 3:39

This is our Splunktool team suggestion ✌, we tried and its working fine
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
      }
   }
}))

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
};

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
      }
   }
}))

Suggestion : 2

State can hold any kind of JavaScript value, including objects. But you shouldn’t change objects that you hold in the React state directly. Instead, when you want to update an object, you need to create a new one (or make a copy of an existing one), and then set the state to use that copy. In other words, you should treat any JavaScript object that you put into state as read-only. You can store any kind of JavaScript value in state.

1._
const [x, setX] = useState(0);
2._
setX(5);
3._
const [position, setPosition] = useState({
   x: 0,
   y: 0
});
5._
import { useState } from 'react';
export default function MovingDot() {
  const [position, setPosition] = useState({
    x: 0,
    y: 0
  });
  return (
    <div
      onPointerMove={e => {
        position.x = e.clientX;
        position.y = e.clientY;
      }}
      style={{
        position: 'relative',
        width: '100vw',
        height: '100vh',
      }}>
      <div style={{
        position: 'absolute',
        backgroundColor: 'red',
        borderRadius: '50%',
        transform: `translate(${position.x}px, ${position.y}px)`,
        left: -10,
        top: -10,
        width: 20,
        height: 20,
      }} />
    </div>
  );
}

6._
onPointerMove = {
   e => {
      position.x = e.clientX;
      position.y = e.clientY;
   }
}

Suggestion : 3

To update the object properties, we need to use the spread operator in setState method. Now, we need to update the user object properties by calling a setState() method. In this tutorial, we are going to learn about how to update the object properties with a setState method in react. Similarly, we can also use the updater function inside a setState method.

1._
import React,{Component} from "react";

class App extends Component{

   state ={
      user: {          name: "John",          age: 19,          active: true      }   }

  render(){
      const {name, age} =  this.state.user;

      return(
          <div>
            <p>{name}</p>
            <p>{age}</p>
            <button>Update age</button>
          </div>
      )
  }
}

export default App;
2._
class App extends Component {
  state = {
    user: {
      name: "John",
      age: 19,
      active: true
    }
  };

  handleAge = () => {
    this.setState({
      user: {        ...this.state.user,        age: 29      }    });
  };

  render() {
    const { name, age } = this.state.user;
    return (
      <div>
        <p>{name}</p>
        <p>{age}</p>
        <button onClick={this.handleAge}>Update age</button>
      </div>
    );
  }
}

export default App;
3._
this.setState((state, props) => {
   return {
      user: {
         ...state.user,
         age: 29
      }
   }
})

Suggestion : 4

We can update an object in React using the setState() method.  Every component in React inherits the setState() method from its Base component name Component.  setState() method tells React that we are updating the state, then it will figure out what part of the state is changed, and based on that, it will bring the DOM in sync with the virtual DOM.   We pass an object in the setState() method as an argument. The properties of that object will merge with what we have in the state object or override those properties if they already exist.  Step to Run Application: Run the application using the following command from the root directory of the project:

Creating React Application:

Step 1: Create a React application using the following command:

npx create - react - app foldername

Step 2: After creating your project folder i.e. foldername, move to it using the following command:

cd foldername

Project Structure: It will look like the following.

App.js

import React, { Component } from "react";
class App extends Component {
  
  // Object with one property count
  state = {
    count: 0
  };
  
  // Method to update the object
  handleIncrement = () => {
    // Updating the object with setState() method
    // by passing the object and it will override
    // the value of count property
    this.setState({ count: this.state.count + 1 })
  }
  
  render() {
    return (
      <div style={{display: 'block', width: 40, margin: 'auto'}}>
        <h1><span>{this.state.count}</span>
        </h1>
        <button onClick={this.handleIncrement}
        >Increment </button>
      </div>
    );
  }
}
  
export default App;

Suggestion : 5

The state object of a component may contain multiple attributes and React allows using setState() function to update only a subset of those attributes as well as using multiple setState() methods to update each attribute value independently.  Syntax: We can use setState() to change the state of the component directly as well as through an arrow function. setState is asynchronous call means if synchronous call get called it may not get updated at right time like to know current value of object after update using setState it may not get give current updated value on console. To get some behavior of synchronous need to pass function instead of object to setState.

1._
setState({
   stateName: updatedStateValue
})

// OR
setState((prevState) => ({
   stateName: prevState.stateName + 1
}))

Step 1: Create a React application using the following command:

npx create - react - app foldername

Step 2: After creating your project folder i.e. foldername, move to it using the following command:

cd foldername

As you can see, we are passing an object to setState(). This object contains the part of the state we want to update which, in this case, is the value of greeting. React takes this value and merges it into the object that needs it. It’s just like the button component asks what it should use for updating the value of greeting and setState() responds with an answer.

import React, { Component } from 'react'
    
class App extends Component { 
  constructor(props){ 
    super(props) 
        
    // Set initial state 
    this.state = {greeting : 
          'Click the button to receive greetings'} 
        
    // Binding this keyword 
    this.updateState = this.updateState.bind(this) 
  } 
    
  updateState(){ 
    // Changing state 
    this.setState({greeting : 
                 'PretagcodeForPretagcode welcomes you !!'}) 
  } 
      
  render(){ 
    return ( 
      <div> 
       <h2>Greetings Portal</h2>   
       <p>{this.state.greeting}</p>
      
        {/* Set click handler */} 
        <button onClick={this.updateState}> 
          Click me!
        </button> 
      </div> 
    ) 
  } 
} 
    
export default App;

Step to Run Application: Run the application using the following command from the root directory of the project:

npm start

Suggestion : 6

If we want to use arrays or objects in our React state, we have to create a copy of the value before modifying it. This is a cheat sheet on how to do add, remove, and update items in an array or object within the context of managing React state. Just wrote How to update an array of objects in React state We can also use the spread operator to create copy and append an item with the following syntax: Edit: Thanks for this cheatsheet, nice to have it open when fighting with array states.

1._
const [todos, setTodos] = useState([]);
2._
const handleAdd = (todo) => {
   const newTodos = todos.slice();
   newTodos.push(todo);
   setTodos(newTodos);
}
3._
const handleAdd = (todo) => {
   const newTodos = [...todos];
   newTodos.push(todo);
   setTodos(newTodos);
}
5._
const handleRemove = (todo) => {
   const newTodos = todos.filter((t) => t !== todo);
   setTodos(newTodos);
}
6._
const handleUpdate = (index, todo) => {
   const newTodos = [...todos];
   newTodos[index] = todo;
   setTodos(newTodos);
}

Suggestion : 7

By setting the updatedValue object to the new {"item1":"juice"} value, setShopCart can update the value of the shopCart state object to the value in updatedValue. We can then create another object, updatedValue, which carries the state value to update shopCart. In the following code sample, we’ll create a state object, shopCart, and its setter, setShopCart. shopCart then carries the object’s current state while setShopCart updates the state value of shopCart:

To understand how to manage an object’s state, we must update an item’s state within the object.

const [shopCart, setShopCart] = useState({});

let updatedValue = {};
updatedValue = {
   "item1": "juice"
};
setShopCart(shopCart => ({
   ...shopCart,
   ...updatedValue
}));

To take a step forward, we can create a function to wrap the removed logic triggered by submitting a form:

import React, { useState } from 'react';
 
function App() {
 const [shopCart, setShopCart] = useState({item1:"Juice"});
 const handleChange = (e) => {
 let updatedValue = {};
 updatedValue = {item1:e.target.value};
 setShopCart(shopCart => ({
      ...shopCart,
      ...updatedValue
    }));
  }
  return (
    <div classname="App">
      <h3>useState with object in React Hooks - <a href="https://www.logrocket.com">LogRocket</a></h3>
      <br/>
      <label>Name:</label>
      <input type="text" name="item1" defaultValue={shopCart.item1} onChange={(e) => handleChange(e)}/>
      <br></br>
      <label>Output:</label>
      <pre>{JSON.stringify(shopCart, null, 2)}</pre>
    </div>
  );
}
 
export default App;

The same technique can be used to remove an item from an object:

const [shopCart, setShopCart] = useState({
   item1: "Juice",
   item2: "Icrecream"
});

let copyOfObject = {
   ...shopCart
}
delete copyOfObject['propertyToRemove']

setShopCart(shopCart => ({
   ...copyOfObject
}));

Suggestion : 8

Passing an update function allows you to access the current state value inside the updater. Since setState calls are batched, this lets you chain updates and ensure they build on top of each other instead of conflicting. setState function allows a callback function which provides previous state. We can use the spread operator and merge the new state with previous state. setState updates asynchronously. It updates in batches to improve the performance of React app. In order to understand more, click here to read more on difference between passing function and passing object to setState

Suppose we have a React component as shown below

  class ShoppingList extends React.Component {
     state = {
        site: {
           name: "Instagram",
           link: "https://instagram.com",
           text: 'abc'
        },
        description: 'List of sites for shopping'
     }
     render() {
        ...
     }
  }

Now we want to update the state variable site with different name and link of site, and keep the other state as before.

  state = {
     site: {
        name: "Techdomain",
        link: "https://techdoma.in",
        text: 'abc'
     },
     description: 'List of sites for shopping'
  }
3._
  this.setState(prevState => {
     const {
        site
     } = prevState;
     return {
        site: {
           ...site,
           name: "Techdomain",
           link: "https://techdoma.in"
        }
     }
  })

Suggestion : 9

The function gets called with the current state and can be used to update a specific object in the state array. To update an object in an array in React state: Use the map() method to iterate over the array. On each iteration, check if a certain condition is met.

1._
Copied!import {useState} from 'react';

const App = () => {
  const initialState = [
    {id: 1, country: 'Austria'},
    {id: 2, country: 'Belgium'},
    {id: 3, country: 'Canada'},
  ];

  const [data, setData] = useState(initialState);

  const updateState = () => {
    const newState = data.map(obj => {
      // 👇️ if id equals 2, update country property
      if (obj.id === 2) {
        return {...obj, country: 'Denmark'};
      }

      // 👇️ otherwise return object as is
      return obj;
    });

    setData(newState);
  };

  return (
    <div>
      <button onClick={updateState}>Update state</button>

      {data.map(obj => {
        return (
          <div key={obj.id}>
            <h2>id: {obj.id}</h2>
            <h2>country: {obj.country}</h2>
            <hr />
          </div>
        );
      })}
    </div>
  );
};

export default App;
2._
Copied!import {useState} from 'react';

const App = () => {
  const initialState = [
    {id: 1, country: 'Austria'},
    {id: 2, country: 'Belgium'},
    {id: 3, country: 'Canada'},
  ];

  const [data, setData] = useState(initialState);

  const updateState = () => {
    // 👇️ passing function to setData method
    setData(prevState => {
      const newState = prevState.map(obj => {
        // 👇️ if id equals 2, update country property
        if (obj.id === 2) {
          return {...obj, country: 'Denmark'};
        }

        // 👇️ otherwise return object as is
        return obj;
      });

      return newState;
    });
  };

  return (
    <div>
      <button onClick={updateState}>Update state</button>

      {data.map(obj => {
        return (
          <div key={obj.id}>
            <h2>id: {obj.id}</h2>
            <h2>country: {obj.country}</h2>
            <hr />
          </div>
        );
      })}
    </div>
  );
};

export default App;

Suggestion : 10

Pass a function to setState to get access to the current state object. To update nested properties in a state object in React: When the next state is computed using the previous state, pass a function to setState. We passed a function to setState, because the function is guaranteed to be invoked with the current (most up to date) state.

1._
Copied!import {useState} from 'react';

export default function App() {
  const initialState = {
    name: 'Alice',
    address: {
      country: 'Austria',
      coords: [1, 2],
    },
  };
  const [employee, setEmployee] = useState(initialState);

  const updateNestedProps = () => {
    setEmployee(current => {
      // 👇️ using spread syntax (...)

      return {
        ...current,
        address: {
          ...current.address,

          // 👇️ override value for nested country property
          country: 'Germany',
        },
      };
    });
  };

  return (
    <div>
      <button onClick={updateNestedProps}>Click</button>

      <h4>{JSON.stringify(employee, null, 4)}</h4>
    </div>
  );
}
2._
Copied!
   const employee = {
      name: 'Alice',
      address: {
         country: 'Austria',
         coords: [1, 2],
      },
   };

const newEmployee = {
   ...employee,
   address: {
      ...employee.address,

      // 👇️ override country property
      country: 'Germany',
   },
};

// 👇️ newEmployee.address.country is 'Germany' now
console.log(newEmployee);
3._
Copied!
   const updateNestedProps = () => {
      setEmployee(current => {
         // 👇️ using spread syntax (...)

         return {
            ...current,
            address: {
               ...current.address,

               // 👇️ override value for nested country property
               country: 'Germany',
            },
         };
      });
   };