Reputation: 11830
I was learning about react hooks and I was going through the example by in the academind,
There the author has mentioned something like this
When you set a new state with React Hooks (i.e. via setCart in our example), the old state will always be replaced!
With probably following example:
import React, { useState } from 'react'
const Shop = props => {
const [cart, setCart] = useState([])
const cartHandler = () => {
setCart(['A Book'])
}
return <button onClick={cartHandler}>Add to Cart</button>
}
I am unable to comprehend this.
In class with the state, If we do setState, it also replaces the old state so what does the author try to mean here?
And later in this article, something like this
If it is an object, just keep in mind that React won’t merge your old state with your new state when you’re setting it. You will always overwrite the old state and hence any merging that might be required has to be done by you!
This all sounds very similar to the setState we do it in class baed component
Upvotes: 6
Views: 4978
Reputation: 17858
When you call setState(), React merges the object you provide into the current state.
With useState updating a state variable always replaces it instead of merging it.
I will try to explain with a sample:
state = {
name: "Michael",
surname: "Jackson"
}
this.setState({
name: "Bill"
})
Here, after the setState, surname didn't lose its value (because setState merges) so state will look like this:
{
name: "Bill",
surname: "Jackson"
}
But if we do it with hooks:
setUser({
name: "Bill"
})
surname is lost, so the state is like this:
{
name: "Bill"
}
To preserve the surname, we can copy the old state using spread operator.
setUser({
...user,
name: "Bill"
});
A complete example:
function App() {
const initialState = { name: "Michael", surname: "Jackson" };
const [user, setUser] = useState(initialState);
const handleClickWrong = () => {
setUser({
name: "Bill"
});
};
const handleClickCorrect = () => {
setUser({
...user,
name: "Bill"
});
};
const handleClickReset = () => {
setUser(initialState);
};
return (
<div className="App">
<button onClick={handleClickWrong}>Change name (wrong)</button>
<button onClick={handleClickCorrect}>Change name (correct)</button>
<button onClick={handleClickReset}>Change name (reset state)</button>
<hr />
{JSON.stringify(user)}
</div>
);
}
Codesandbox:
https://codesandbox.io/s/hook-not-merging-state-cqj2g
Upvotes: 13
Reputation: 2931
If it is an object, just keep in mind that React won’t merge your old state with your new state when you’re setting it. You will always overwrite the old state and hence any merging that might be required has to be done by you!
His statement that's mean, when you initial state with an object
const [cart, setCart] = useState([])
or
const [cart, setCart] = useState({})
when setState you want to add new state into old state, you have to override your old state. You can use es6 Destructuring_assignment
setCart([...cart, newCartArray])
or
setCart({...cart, newCartObject})
If you don't do that, your new state will be replaced instead of override and you will lose your old state.
Upvotes: -1