Reputation: 1193
I have this component using Hooks:
function App() {
const [text, setText] = useState({ h1: "hello", h2: "hi" });
const changeH1 = () => {
setText({
...text,
h1: text.h1 + "C"
});
};
const changeH2 = () => {
setText({
...text,
h2: text.h2 + "X"
});
};
const changeAll = () => {
changeH1();
changeH2();
};
return (
<div className="App">
<h1 onClick={() => changeH1()}>{text.h1}</h1>
<h1 onClick={() => changeH2()}>{text.h2}</h1>
<button onClick={() => changeAll()}>Change</button>
</div>
);
}
It will display two headings with some text and a button. When I click on the first heading, the "C" character will be added to the heading. When I click on the second heading, the "X" character will be added to the heading. When I click the button, it will do two actions above at the same time.
It works fine on two headings but the button. When I click the button, only the second heading changes. I think that the setText
of changeH1
and changeH2
are not working when they are called in changeAll
. What's wrong with my code?
Upvotes: 3
Views: 1470
Reputation: 22304
Because changeH2()
overwrites h1
property by doing ...text
.
The 2 setText()
calls are executed before a re-render - I believe it's due to batching as explained in https://overreacted.io/react-as-a-ui-runtime/#batching
A solution would be to use a simple state instead of an object:
const [h1, setH1] = useState("hello");
const [h2, setH2] = useState("hi");
...
Or else useReducer
for more complex operations https://reactjs.org/docs/hooks-reference.html#usereducer
Upvotes: 1