Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating and merging state object using React useState() hook

I'm finding these two pieces of the React Hooks docs a little confusing. Which one is the best practice for updating a state object using the state hook?

Imagine a want to make the following state update:

INITIAL_STATE = {   propA: true,   propB: true }  stateAfter = {   propA: true,   propB: false   // Changing this property } 

OPTION 1

From the Using the React Hook article, we get that this is possible:

const [count, setCount] = useState(0); setCount(count + 1); 

So I could do:

const [myState, setMyState] = useState(INITIAL_STATE); 

And then:

setMyState({   ...myState,   propB: false }); 

OPTION 2

And from the Hooks Reference we get that:

Unlike the setState method found in class components, useState does not automatically merge update objects. You can replicate this behavior by combining the function updater form with object spread syntax:

setState(prevState => {   // Object.assign would also work   return {...prevState, ...updatedValues}; }); 

As far as I know, both works. So, what is the difference? Which one is the best practice? Should I use pass the function (OPTION 2) to access the previous state, or should I simply access the current state with spread syntax (OPTION 1)?

like image 624
cbdeveloper Avatar asked Mar 25 '19 16:03

cbdeveloper


Video Answer


1 Answers

Both options are valid, but just as with setState in a class component you need to be careful when updating state derived from something that already is in state.

If you e.g. update a count twice in a row, it will not work as expected if you don't use the function version of updating the state.

const { useState } = React;    function App() {    const [count, setCount] = useState(0);      function brokenIncrement() {      setCount(count + 1);      setCount(count + 1);    }      function increment() {      setCount(count => count + 1);      setCount(count => count + 1);    }      return (      <div>        <div>{count}</div>        <button onClick={brokenIncrement}>Broken increment</button>        <button onClick={increment}>Increment</button>      </div>    );  }    ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>  <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>    <div id="root"></div>
like image 89
Tholle Avatar answered Oct 13 '22 14:10

Tholle