useState hook setter incorrectly overwrites stateReact useState Hook setter has no result with array variableUpdating and merging state object using React useState() hookReact Hook “useState” is called in function “setResults” which is neither a React function component or a custom React Hook functionTesting useState in ReactuseState-hook is not updating my state in an onPress() functionHow to set initial state for useState Hook in jest and enzyme?useState in react hooks converting to functional componentReact useState Hooks - managing multiple loading states within a stateCorrect way of using useState hook on radio buttons
How to explain my complicated family background to people that I don't know very well?
As a DM, what are important changes to the play caused by Detect Magic no longer being a cantrip in 5e?
Is it ethical to apply for a short-term grant with a partner/spouse/girlfriend?
How can I smoothly transition between two UV maps?
What did Harry mean when he said "Well, I take it you're not sorry?" to Griphook?
Which floor is the Hogwarts Library on?
Change cone width
Why has Trump refused to recognize the Armenian Genocide?
Equivalent circuit of a non-ideal resistor
Peptide bond formation involving side chains of charged amino acids
Was I wrong to rebutt unjustified rewiewer comments in the review?
Has a remote rogue DNS client managed to slip through the first iptables rule of a Linux DNS server?
What is separation between policy and mechanism?
I don't feel like creating this riddle today
Can a public school in the USA force a 14yr old to create a Twitter account for a passing grade?
Advent calendar
Toxic culture - I'm putting in more resources to help the project move faster, but people are slowing down
Java OOP Temperature Converter
What bit should I use to drill a two inch hole in a solid concrete wall?
What is a Brown Bag Seminar?
Does the three-clause BSD license hinder academic citations?
Why is f'74' the same as f'74' with f-Strings?
Is it possible to conserve the total kinetic energy of a system, but not its momentum?
Do not combine certain elements in Split or SplitBy
useState hook setter incorrectly overwrites state
React useState Hook setter has no result with array variableUpdating and merging state object using React useState() hookReact Hook “useState” is called in function “setResults” which is neither a React function component or a custom React Hook functionTesting useState in ReactuseState-hook is not updating my state in an onPress() functionHow to set initial state for useState Hook in jest and enzyme?useState in react hooks converting to functional componentReact useState Hooks - managing multiple loading states within a stateCorrect way of using useState hook on radio buttons
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;
Here's the issue: I'm trying to call 2 functions on a button click. Both functions update the state (I'm using the useState hook). First function updates value1 correctly to 'new 1', but after 1s (setTimeout) second function fires, and it changes value 2 to 'new 2' BUT! It set's value1 back to '1'. Why is this happening?
Thanks in advance!
import React, useState from "react";
const Test = () =>
const [state, setState] = useState(
value1: "1",
value2: "2"
);
const changeValue1 = () =>
setState( ...state, value1: "new 1" );
;
const changeValue2 = () =>
setState( ...state, value2: "new 2" );
;
return (
<>
<button
onClick=() =>
changeValue1();
setTimeout(changeValue2, 1000);
>
CHANGE BOTH
</button>
<h1>state.value1</h1>
<h1>state.value2</h1>
</>
);
;
export default Test;
javascript reactjs react-hooks
add a comment
|
Here's the issue: I'm trying to call 2 functions on a button click. Both functions update the state (I'm using the useState hook). First function updates value1 correctly to 'new 1', but after 1s (setTimeout) second function fires, and it changes value 2 to 'new 2' BUT! It set's value1 back to '1'. Why is this happening?
Thanks in advance!
import React, useState from "react";
const Test = () =>
const [state, setState] = useState(
value1: "1",
value2: "2"
);
const changeValue1 = () =>
setState( ...state, value1: "new 1" );
;
const changeValue2 = () =>
setState( ...state, value2: "new 2" );
;
return (
<>
<button
onClick=() =>
changeValue1();
setTimeout(changeValue2, 1000);
>
CHANGE BOTH
</button>
<h1>state.value1</h1>
<h1>state.value2</h1>
</>
);
;
export default Test;
javascript reactjs react-hooks
could you log state at the start ofchangeValue2
?
– DanStarns
Oct 1 at 22:46
1
I highly recommend that you either split the object into two separate calls touseState
or instead useuseReducer
.
– Jared Smith
Oct 2 at 11:15
Yes - second this. Just use two calls to useState()
– Esben Skov Pedersen
Oct 2 at 15:49
const [state, ...]
, and then referring to it in the setter... It will use the same state all the time.
– Johannes Kuhn
Oct 2 at 20:07
Best course of action: use 2 separateuseState
calls, one for each "variable".
– Dima Tisnek
Oct 24 at 2:48
add a comment
|
Here's the issue: I'm trying to call 2 functions on a button click. Both functions update the state (I'm using the useState hook). First function updates value1 correctly to 'new 1', but after 1s (setTimeout) second function fires, and it changes value 2 to 'new 2' BUT! It set's value1 back to '1'. Why is this happening?
Thanks in advance!
import React, useState from "react";
const Test = () =>
const [state, setState] = useState(
value1: "1",
value2: "2"
);
const changeValue1 = () =>
setState( ...state, value1: "new 1" );
;
const changeValue2 = () =>
setState( ...state, value2: "new 2" );
;
return (
<>
<button
onClick=() =>
changeValue1();
setTimeout(changeValue2, 1000);
>
CHANGE BOTH
</button>
<h1>state.value1</h1>
<h1>state.value2</h1>
</>
);
;
export default Test;
javascript reactjs react-hooks
Here's the issue: I'm trying to call 2 functions on a button click. Both functions update the state (I'm using the useState hook). First function updates value1 correctly to 'new 1', but after 1s (setTimeout) second function fires, and it changes value 2 to 'new 2' BUT! It set's value1 back to '1'. Why is this happening?
Thanks in advance!
import React, useState from "react";
const Test = () =>
const [state, setState] = useState(
value1: "1",
value2: "2"
);
const changeValue1 = () =>
setState( ...state, value1: "new 1" );
;
const changeValue2 = () =>
setState( ...state, value2: "new 2" );
;
return (
<>
<button
onClick=() =>
changeValue1();
setTimeout(changeValue2, 1000);
>
CHANGE BOTH
</button>
<h1>state.value1</h1>
<h1>state.value2</h1>
</>
);
;
export default Test;
javascript reactjs react-hooks
javascript reactjs react-hooks
edited Oct 1 at 23:16
Jee Mok
2,3906 gold badges19 silver badges45 bronze badges
2,3906 gold badges19 silver badges45 bronze badges
asked Oct 1 at 22:40
BartekBartek
3031 silver badge5 bronze badges
3031 silver badge5 bronze badges
could you log state at the start ofchangeValue2
?
– DanStarns
Oct 1 at 22:46
1
I highly recommend that you either split the object into two separate calls touseState
or instead useuseReducer
.
– Jared Smith
Oct 2 at 11:15
Yes - second this. Just use two calls to useState()
– Esben Skov Pedersen
Oct 2 at 15:49
const [state, ...]
, and then referring to it in the setter... It will use the same state all the time.
– Johannes Kuhn
Oct 2 at 20:07
Best course of action: use 2 separateuseState
calls, one for each "variable".
– Dima Tisnek
Oct 24 at 2:48
add a comment
|
could you log state at the start ofchangeValue2
?
– DanStarns
Oct 1 at 22:46
1
I highly recommend that you either split the object into two separate calls touseState
or instead useuseReducer
.
– Jared Smith
Oct 2 at 11:15
Yes - second this. Just use two calls to useState()
– Esben Skov Pedersen
Oct 2 at 15:49
const [state, ...]
, and then referring to it in the setter... It will use the same state all the time.
– Johannes Kuhn
Oct 2 at 20:07
Best course of action: use 2 separateuseState
calls, one for each "variable".
– Dima Tisnek
Oct 24 at 2:48
could you log state at the start of
changeValue2
?– DanStarns
Oct 1 at 22:46
could you log state at the start of
changeValue2
?– DanStarns
Oct 1 at 22:46
1
1
I highly recommend that you either split the object into two separate calls to
useState
or instead use useReducer
.– Jared Smith
Oct 2 at 11:15
I highly recommend that you either split the object into two separate calls to
useState
or instead use useReducer
.– Jared Smith
Oct 2 at 11:15
Yes - second this. Just use two calls to useState()
– Esben Skov Pedersen
Oct 2 at 15:49
Yes - second this. Just use two calls to useState()
– Esben Skov Pedersen
Oct 2 at 15:49
const [state, ...]
, and then referring to it in the setter... It will use the same state all the time.– Johannes Kuhn
Oct 2 at 20:07
const [state, ...]
, and then referring to it in the setter... It will use the same state all the time.– Johannes Kuhn
Oct 2 at 20:07
Best course of action: use 2 separate
useState
calls, one for each "variable".– Dima Tisnek
Oct 24 at 2:48
Best course of action: use 2 separate
useState
calls, one for each "variable".– Dima Tisnek
Oct 24 at 2:48
add a comment
|
4 Answers
4
active
oldest
votes
Welcome to the closure hell. This issue happens because whenever setState
is called, state
gets a new memory reference, but the functions changeValue1
and changeValue2
, because of closure, keep the old initial state
reference.
A solution to ensure the setState
from changeValue1
and changeValue2
gets the latest state is by using a callback (having the fresh current state as a parameter):
import React, useState from "react";
const Test = () =>
const [state, setState] = useState(
value1: "1",
value2: "2"
);
const changeValue1 = () =>
setState((state) => ( ...state, value1: "new 1" ));
;
const changeValue2 = () =>
setState((state) => ( ...state, value2: "new 2" ));
;
// ...
;
You can find a broader discussion about this closure issue here and here.
A callback with useState hook seems to be an undocumented feature, are you sure that works?
– HMR
Oct 2 at 7:32
@HMR Yes, it works and it's documented on another page. Take a look at the "Functional updates" section here: reactjs.org/docs/hooks-reference.html ("If the new state is computed using the previous state, you can pass a function to setState")
– Alberto Trindade Tavares
Oct 2 at 7:45
@HMR But, to be honest, they could have done a better job in making this more visible.
– Alberto Trindade Tavares
Oct 2 at 7:47
1
@AlbertoTrindadeTavares Yes, I was looking at the docs aswell, couldnt find anything. Thanks a lot for the answer!
– Bartek
Oct 2 at 7:53
1
Your first solution isn't just an "easy solution", it's the correct method. The second one would only work if the component is designed as a singleton, and even then i'm not sure about that because state becomes a new object each time.
– Scimonster
Oct 2 at 10:45
|
show 2 more comments
Your functions should be like this:
const changeValue1 = () =>
setState((prevState) => ( ...prevState, value1: "new 1" ));
;
const changeValue2 = () =>
setState((prevState) => ( ...prevState, value2: "new 2" ));
;
Thus you make sure you are not missing any existing property in the current state by using the previous state when the action is fired. Also thus you avoid to have to manage closures.
add a comment
|
When changeValue2
is invoked, initial state is held so the state turns back to the inital state and then value2
property is written.
Next time changeValue2
is invoked after that, it holds the state value1: "1", value2: "new 2"
, so value1
property is overwritten.
You need an arrow function for the setState
parameter.
const Test = () =>
const [state, setState] = React.useState(
value1: "1",
value2: "2"
);
const changeValue1 = () =>
setState(prev => ( ...prev, value1: "new 1" ));
;
const changeValue2 = () =>
setState(prev => ( ...prev, value2: "new 2" ));
;
return (
<React.Fragment>
<button
onClick=() =>
changeValue1();
setTimeout(changeValue2, 1000);
>
CHANGE BOTH
</button>
<h1>state.value1</h1>
<h1>state.value2</h1>
</React.Fragment>
);
;
ReactDOM.render(<Test />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
add a comment
|
What's happening is that both changeValue1
and changeValue2
see the state from the render they were created in, so when your component render for the first time these 2 functions see:
state=
value1: "1",
value2: "2"
When you click on the button, changeValue1
is called first and changes the state to value1: "new1", value2: "2"
as expected.
Now, after 1 second, changeValue2
is called, but this function still see the initial state (value1; "1", value2: "2"
), so when this function updates the state this way:
setState( ...state, value2: "new 2" );
you end up seeing: value1; "1", value2: "new2"
.
source
add a comment
|
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f58193166%2fusestate-hook-setter-incorrectly-overwrites-state%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
Welcome to the closure hell. This issue happens because whenever setState
is called, state
gets a new memory reference, but the functions changeValue1
and changeValue2
, because of closure, keep the old initial state
reference.
A solution to ensure the setState
from changeValue1
and changeValue2
gets the latest state is by using a callback (having the fresh current state as a parameter):
import React, useState from "react";
const Test = () =>
const [state, setState] = useState(
value1: "1",
value2: "2"
);
const changeValue1 = () =>
setState((state) => ( ...state, value1: "new 1" ));
;
const changeValue2 = () =>
setState((state) => ( ...state, value2: "new 2" ));
;
// ...
;
You can find a broader discussion about this closure issue here and here.
A callback with useState hook seems to be an undocumented feature, are you sure that works?
– HMR
Oct 2 at 7:32
@HMR Yes, it works and it's documented on another page. Take a look at the "Functional updates" section here: reactjs.org/docs/hooks-reference.html ("If the new state is computed using the previous state, you can pass a function to setState")
– Alberto Trindade Tavares
Oct 2 at 7:45
@HMR But, to be honest, they could have done a better job in making this more visible.
– Alberto Trindade Tavares
Oct 2 at 7:47
1
@AlbertoTrindadeTavares Yes, I was looking at the docs aswell, couldnt find anything. Thanks a lot for the answer!
– Bartek
Oct 2 at 7:53
1
Your first solution isn't just an "easy solution", it's the correct method. The second one would only work if the component is designed as a singleton, and even then i'm not sure about that because state becomes a new object each time.
– Scimonster
Oct 2 at 10:45
|
show 2 more comments
Welcome to the closure hell. This issue happens because whenever setState
is called, state
gets a new memory reference, but the functions changeValue1
and changeValue2
, because of closure, keep the old initial state
reference.
A solution to ensure the setState
from changeValue1
and changeValue2
gets the latest state is by using a callback (having the fresh current state as a parameter):
import React, useState from "react";
const Test = () =>
const [state, setState] = useState(
value1: "1",
value2: "2"
);
const changeValue1 = () =>
setState((state) => ( ...state, value1: "new 1" ));
;
const changeValue2 = () =>
setState((state) => ( ...state, value2: "new 2" ));
;
// ...
;
You can find a broader discussion about this closure issue here and here.
A callback with useState hook seems to be an undocumented feature, are you sure that works?
– HMR
Oct 2 at 7:32
@HMR Yes, it works and it's documented on another page. Take a look at the "Functional updates" section here: reactjs.org/docs/hooks-reference.html ("If the new state is computed using the previous state, you can pass a function to setState")
– Alberto Trindade Tavares
Oct 2 at 7:45
@HMR But, to be honest, they could have done a better job in making this more visible.
– Alberto Trindade Tavares
Oct 2 at 7:47
1
@AlbertoTrindadeTavares Yes, I was looking at the docs aswell, couldnt find anything. Thanks a lot for the answer!
– Bartek
Oct 2 at 7:53
1
Your first solution isn't just an "easy solution", it's the correct method. The second one would only work if the component is designed as a singleton, and even then i'm not sure about that because state becomes a new object each time.
– Scimonster
Oct 2 at 10:45
|
show 2 more comments
Welcome to the closure hell. This issue happens because whenever setState
is called, state
gets a new memory reference, but the functions changeValue1
and changeValue2
, because of closure, keep the old initial state
reference.
A solution to ensure the setState
from changeValue1
and changeValue2
gets the latest state is by using a callback (having the fresh current state as a parameter):
import React, useState from "react";
const Test = () =>
const [state, setState] = useState(
value1: "1",
value2: "2"
);
const changeValue1 = () =>
setState((state) => ( ...state, value1: "new 1" ));
;
const changeValue2 = () =>
setState((state) => ( ...state, value2: "new 2" ));
;
// ...
;
You can find a broader discussion about this closure issue here and here.
Welcome to the closure hell. This issue happens because whenever setState
is called, state
gets a new memory reference, but the functions changeValue1
and changeValue2
, because of closure, keep the old initial state
reference.
A solution to ensure the setState
from changeValue1
and changeValue2
gets the latest state is by using a callback (having the fresh current state as a parameter):
import React, useState from "react";
const Test = () =>
const [state, setState] = useState(
value1: "1",
value2: "2"
);
const changeValue1 = () =>
setState((state) => ( ...state, value1: "new 1" ));
;
const changeValue2 = () =>
setState((state) => ( ...state, value2: "new 2" ));
;
// ...
;
You can find a broader discussion about this closure issue here and here.
edited Nov 5 at 9:20
answered Oct 1 at 23:08
Alberto Trindade TavaresAlberto Trindade Tavares
6,02319 silver badges31 bronze badges
6,02319 silver badges31 bronze badges
A callback with useState hook seems to be an undocumented feature, are you sure that works?
– HMR
Oct 2 at 7:32
@HMR Yes, it works and it's documented on another page. Take a look at the "Functional updates" section here: reactjs.org/docs/hooks-reference.html ("If the new state is computed using the previous state, you can pass a function to setState")
– Alberto Trindade Tavares
Oct 2 at 7:45
@HMR But, to be honest, they could have done a better job in making this more visible.
– Alberto Trindade Tavares
Oct 2 at 7:47
1
@AlbertoTrindadeTavares Yes, I was looking at the docs aswell, couldnt find anything. Thanks a lot for the answer!
– Bartek
Oct 2 at 7:53
1
Your first solution isn't just an "easy solution", it's the correct method. The second one would only work if the component is designed as a singleton, and even then i'm not sure about that because state becomes a new object each time.
– Scimonster
Oct 2 at 10:45
|
show 2 more comments
A callback with useState hook seems to be an undocumented feature, are you sure that works?
– HMR
Oct 2 at 7:32
@HMR Yes, it works and it's documented on another page. Take a look at the "Functional updates" section here: reactjs.org/docs/hooks-reference.html ("If the new state is computed using the previous state, you can pass a function to setState")
– Alberto Trindade Tavares
Oct 2 at 7:45
@HMR But, to be honest, they could have done a better job in making this more visible.
– Alberto Trindade Tavares
Oct 2 at 7:47
1
@AlbertoTrindadeTavares Yes, I was looking at the docs aswell, couldnt find anything. Thanks a lot for the answer!
– Bartek
Oct 2 at 7:53
1
Your first solution isn't just an "easy solution", it's the correct method. The second one would only work if the component is designed as a singleton, and even then i'm not sure about that because state becomes a new object each time.
– Scimonster
Oct 2 at 10:45
A callback with useState hook seems to be an undocumented feature, are you sure that works?
– HMR
Oct 2 at 7:32
A callback with useState hook seems to be an undocumented feature, are you sure that works?
– HMR
Oct 2 at 7:32
@HMR Yes, it works and it's documented on another page. Take a look at the "Functional updates" section here: reactjs.org/docs/hooks-reference.html ("If the new state is computed using the previous state, you can pass a function to setState")
– Alberto Trindade Tavares
Oct 2 at 7:45
@HMR Yes, it works and it's documented on another page. Take a look at the "Functional updates" section here: reactjs.org/docs/hooks-reference.html ("If the new state is computed using the previous state, you can pass a function to setState")
– Alberto Trindade Tavares
Oct 2 at 7:45
@HMR But, to be honest, they could have done a better job in making this more visible.
– Alberto Trindade Tavares
Oct 2 at 7:47
@HMR But, to be honest, they could have done a better job in making this more visible.
– Alberto Trindade Tavares
Oct 2 at 7:47
1
1
@AlbertoTrindadeTavares Yes, I was looking at the docs aswell, couldnt find anything. Thanks a lot for the answer!
– Bartek
Oct 2 at 7:53
@AlbertoTrindadeTavares Yes, I was looking at the docs aswell, couldnt find anything. Thanks a lot for the answer!
– Bartek
Oct 2 at 7:53
1
1
Your first solution isn't just an "easy solution", it's the correct method. The second one would only work if the component is designed as a singleton, and even then i'm not sure about that because state becomes a new object each time.
– Scimonster
Oct 2 at 10:45
Your first solution isn't just an "easy solution", it's the correct method. The second one would only work if the component is designed as a singleton, and even then i'm not sure about that because state becomes a new object each time.
– Scimonster
Oct 2 at 10:45
|
show 2 more comments
Your functions should be like this:
const changeValue1 = () =>
setState((prevState) => ( ...prevState, value1: "new 1" ));
;
const changeValue2 = () =>
setState((prevState) => ( ...prevState, value2: "new 2" ));
;
Thus you make sure you are not missing any existing property in the current state by using the previous state when the action is fired. Also thus you avoid to have to manage closures.
add a comment
|
Your functions should be like this:
const changeValue1 = () =>
setState((prevState) => ( ...prevState, value1: "new 1" ));
;
const changeValue2 = () =>
setState((prevState) => ( ...prevState, value2: "new 2" ));
;
Thus you make sure you are not missing any existing property in the current state by using the previous state when the action is fired. Also thus you avoid to have to manage closures.
add a comment
|
Your functions should be like this:
const changeValue1 = () =>
setState((prevState) => ( ...prevState, value1: "new 1" ));
;
const changeValue2 = () =>
setState((prevState) => ( ...prevState, value2: "new 2" ));
;
Thus you make sure you are not missing any existing property in the current state by using the previous state when the action is fired. Also thus you avoid to have to manage closures.
Your functions should be like this:
const changeValue1 = () =>
setState((prevState) => ( ...prevState, value1: "new 1" ));
;
const changeValue2 = () =>
setState((prevState) => ( ...prevState, value2: "new 2" ));
;
Thus you make sure you are not missing any existing property in the current state by using the previous state when the action is fired. Also thus you avoid to have to manage closures.
edited Oct 1 at 23:13
answered Oct 1 at 23:08
DezDez
4,1406 gold badges31 silver badges43 bronze badges
4,1406 gold badges31 silver badges43 bronze badges
add a comment
|
add a comment
|
When changeValue2
is invoked, initial state is held so the state turns back to the inital state and then value2
property is written.
Next time changeValue2
is invoked after that, it holds the state value1: "1", value2: "new 2"
, so value1
property is overwritten.
You need an arrow function for the setState
parameter.
const Test = () =>
const [state, setState] = React.useState(
value1: "1",
value2: "2"
);
const changeValue1 = () =>
setState(prev => ( ...prev, value1: "new 1" ));
;
const changeValue2 = () =>
setState(prev => ( ...prev, value2: "new 2" ));
;
return (
<React.Fragment>
<button
onClick=() =>
changeValue1();
setTimeout(changeValue2, 1000);
>
CHANGE BOTH
</button>
<h1>state.value1</h1>
<h1>state.value2</h1>
</React.Fragment>
);
;
ReactDOM.render(<Test />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
add a comment
|
When changeValue2
is invoked, initial state is held so the state turns back to the inital state and then value2
property is written.
Next time changeValue2
is invoked after that, it holds the state value1: "1", value2: "new 2"
, so value1
property is overwritten.
You need an arrow function for the setState
parameter.
const Test = () =>
const [state, setState] = React.useState(
value1: "1",
value2: "2"
);
const changeValue1 = () =>
setState(prev => ( ...prev, value1: "new 1" ));
;
const changeValue2 = () =>
setState(prev => ( ...prev, value2: "new 2" ));
;
return (
<React.Fragment>
<button
onClick=() =>
changeValue1();
setTimeout(changeValue2, 1000);
>
CHANGE BOTH
</button>
<h1>state.value1</h1>
<h1>state.value2</h1>
</React.Fragment>
);
;
ReactDOM.render(<Test />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
add a comment
|
When changeValue2
is invoked, initial state is held so the state turns back to the inital state and then value2
property is written.
Next time changeValue2
is invoked after that, it holds the state value1: "1", value2: "new 2"
, so value1
property is overwritten.
You need an arrow function for the setState
parameter.
const Test = () =>
const [state, setState] = React.useState(
value1: "1",
value2: "2"
);
const changeValue1 = () =>
setState(prev => ( ...prev, value1: "new 1" ));
;
const changeValue2 = () =>
setState(prev => ( ...prev, value2: "new 2" ));
;
return (
<React.Fragment>
<button
onClick=() =>
changeValue1();
setTimeout(changeValue2, 1000);
>
CHANGE BOTH
</button>
<h1>state.value1</h1>
<h1>state.value2</h1>
</React.Fragment>
);
;
ReactDOM.render(<Test />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
When changeValue2
is invoked, initial state is held so the state turns back to the inital state and then value2
property is written.
Next time changeValue2
is invoked after that, it holds the state value1: "1", value2: "new 2"
, so value1
property is overwritten.
You need an arrow function for the setState
parameter.
const Test = () =>
const [state, setState] = React.useState(
value1: "1",
value2: "2"
);
const changeValue1 = () =>
setState(prev => ( ...prev, value1: "new 1" ));
;
const changeValue2 = () =>
setState(prev => ( ...prev, value2: "new 2" ));
;
return (
<React.Fragment>
<button
onClick=() =>
changeValue1();
setTimeout(changeValue2, 1000);
>
CHANGE BOTH
</button>
<h1>state.value1</h1>
<h1>state.value2</h1>
</React.Fragment>
);
;
ReactDOM.render(<Test />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
const Test = () =>
const [state, setState] = React.useState(
value1: "1",
value2: "2"
);
const changeValue1 = () =>
setState(prev => ( ...prev, value1: "new 1" ));
;
const changeValue2 = () =>
setState(prev => ( ...prev, value2: "new 2" ));
;
return (
<React.Fragment>
<button
onClick=() =>
changeValue1();
setTimeout(changeValue2, 1000);
>
CHANGE BOTH
</button>
<h1>state.value1</h1>
<h1>state.value2</h1>
</React.Fragment>
);
;
ReactDOM.render(<Test />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
const Test = () =>
const [state, setState] = React.useState(
value1: "1",
value2: "2"
);
const changeValue1 = () =>
setState(prev => ( ...prev, value1: "new 1" ));
;
const changeValue2 = () =>
setState(prev => ( ...prev, value2: "new 2" ));
;
return (
<React.Fragment>
<button
onClick=() =>
changeValue1();
setTimeout(changeValue2, 1000);
>
CHANGE BOTH
</button>
<h1>state.value1</h1>
<h1>state.value2</h1>
</React.Fragment>
);
;
ReactDOM.render(<Test />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
edited Oct 2 at 9:34
answered Oct 1 at 23:21
zmagzmag
4,4128 gold badges18 silver badges28 bronze badges
4,4128 gold badges18 silver badges28 bronze badges
add a comment
|
add a comment
|
What's happening is that both changeValue1
and changeValue2
see the state from the render they were created in, so when your component render for the first time these 2 functions see:
state=
value1: "1",
value2: "2"
When you click on the button, changeValue1
is called first and changes the state to value1: "new1", value2: "2"
as expected.
Now, after 1 second, changeValue2
is called, but this function still see the initial state (value1; "1", value2: "2"
), so when this function updates the state this way:
setState( ...state, value2: "new 2" );
you end up seeing: value1; "1", value2: "new2"
.
source
add a comment
|
What's happening is that both changeValue1
and changeValue2
see the state from the render they were created in, so when your component render for the first time these 2 functions see:
state=
value1: "1",
value2: "2"
When you click on the button, changeValue1
is called first and changes the state to value1: "new1", value2: "2"
as expected.
Now, after 1 second, changeValue2
is called, but this function still see the initial state (value1; "1", value2: "2"
), so when this function updates the state this way:
setState( ...state, value2: "new 2" );
you end up seeing: value1; "1", value2: "new2"
.
source
add a comment
|
What's happening is that both changeValue1
and changeValue2
see the state from the render they were created in, so when your component render for the first time these 2 functions see:
state=
value1: "1",
value2: "2"
When you click on the button, changeValue1
is called first and changes the state to value1: "new1", value2: "2"
as expected.
Now, after 1 second, changeValue2
is called, but this function still see the initial state (value1; "1", value2: "2"
), so when this function updates the state this way:
setState( ...state, value2: "new 2" );
you end up seeing: value1; "1", value2: "new2"
.
source
What's happening is that both changeValue1
and changeValue2
see the state from the render they were created in, so when your component render for the first time these 2 functions see:
state=
value1: "1",
value2: "2"
When you click on the button, changeValue1
is called first and changes the state to value1: "new1", value2: "2"
as expected.
Now, after 1 second, changeValue2
is called, but this function still see the initial state (value1; "1", value2: "2"
), so when this function updates the state this way:
setState( ...state, value2: "new 2" );
you end up seeing: value1; "1", value2: "new2"
.
source
answered Oct 1 at 23:12
El Aoutar HamzaEl Aoutar Hamza
2,4731 gold badge5 silver badges15 bronze badges
2,4731 gold badge5 silver badges15 bronze badges
add a comment
|
add a comment
|
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f58193166%2fusestate-hook-setter-incorrectly-overwrites-state%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
could you log state at the start of
changeValue2
?– DanStarns
Oct 1 at 22:46
1
I highly recommend that you either split the object into two separate calls to
useState
or instead useuseReducer
.– Jared Smith
Oct 2 at 11:15
Yes - second this. Just use two calls to useState()
– Esben Skov Pedersen
Oct 2 at 15:49
const [state, ...]
, and then referring to it in the setter... It will use the same state all the time.– Johannes Kuhn
Oct 2 at 20:07
Best course of action: use 2 separate
useState
calls, one for each "variable".– Dima Tisnek
Oct 24 at 2:48