简体   繁体   中英

What is the proper flow to merge the previous state with the new state on a useState hook?

Let's say I have this on my initial state:

  let initialStoreState = {
    products: [],
    checkout: [],
    adding: false,
    loading: true
  }

  const [store, updateStore] = useState(initialStoreState)

  useEffect(() => {
    if(someValue) {
        // pay attention to this code below
        updateStore((prevState) => {
          return { ...prevState, checkout, loading: false }
        })
    }
  }, [someValue]}

So would you use it like that on updateStore or like this:

// this is how I normally see it being used
updateStore({ ...store, checkout, loading: false })

Is there any difference or mutability issues in one or another?

If the question is about whether to use the functional update or to use state value directly to update the state, in most cases updating the state directly will work.

// will work most of the times
updateStore({ ...store, checkout, loading: false })

But it is very easy to run into issues where the outdated state value will get captured as a result of a closure . The simplest example would be if the callback passed to a setTimeout or setInterval tries to update the state value directly it may not produce the expected result.

To fix the closure issue we can use functional updates

// example from the current use case
updateStore((prevState) => {
    return { ...prevState, checkout, loading: false }
})

Here is an example codesandbox with a demonstration of the closure issue.

However, for your current use case useReducer seems more appropriate and it is the suggested way of managing a state object with multiple sub-values.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM