Reputation: 343
Would like to know if there is a way to update nested object states in React using useState()
import React, {useState} from 'react'
const MyComp = () => {
const [colors, setColors] = useState({colorA: 'RED', colorB: 'PURPLE'});
return (
<div>
<span>{colors.colorB}</span>
<button onClick={() => setColors({...colors, colors: { colorB: 'WHITE'}})}>CLICK ME</button>
</div>
)
}
export default MyComp;
I was thinking to use useReducer() but I read that It's normally use for more complex states and maybe there is a solution for this case just using useState()
Any ideas?
Thx in advance
Upvotes: 2
Views: 306
Reputation: 1864
There was a minor syntax error in the statement
const App = () => {
const [colors, setColors] = useState({ colorA: 'RED', colorB: 'PURPLE' });
return (
<div>
<span>{colors.colorB}</span>
<button onClick={
() =>
setColors(
{ ...colors,colorB: 'WHITE' }
)
}>CLICK ME</button>
</div>
)
}
Upvotes: 0
Reputation: 9135
Since you have already done the spread, it will have the property colorB, you just need to update with new value
const handleButtonClick = () => {
setColors({ ...colors, colorB: "WHITE" });
};
making it into a function will be more readable.
Code
import React, { useState } from "react";
import ReactDOM from "react-dom";
const MyComp = () => {
const [colors, setColors] = useState({ colorA: "RED", colorB: "PURPLE" });
const handleButtonClick = () => {
setColors({ ...colors, colorB: "WHITE" });
};
return (
<div>
<span>{colors.colorB}</span>
<button onClick={handleButtonClick}>CLICK ME</button>
</div>
);
};
export default MyComp;
const rootElement = document.getElementById("root");
ReactDOM.render(<MyComp />, rootElement);
Working Codepen
Upvotes: 2
Reputation: 383
USE
setColors({...colors, colorB: 'WHITE'})
INSTEAD OF
setColors({...colors, colors: { colorB: 'WHITE'}})
Upvotes: 4
Reputation: 10873
It's better to use functional form of setState
for this, since the next state value depends on the current value of the state:
return (
<div>
<span>{colors.colorB}</span>
<button
onClick={() => setColors(currentColors => ({ ...currentColors, colorB: "WHITE" }))}
>
CLICK ME
</button>
</div>
);
Upvotes: 3
Reputation: 2252
You are updating the state in a wrong way. Change your button statement to below,
<button onClick={() => setColors({...colors, colorB: 'WHITE'})}>CLICK ME</button>
Upvotes: 4
Reputation: 21357
colors
already is the whole object, you don't need to declare as a property.
spread
the original object and override colorB
() => setColors({...colors, colorB: 'WHITE'})
Upvotes: 4