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;









30


















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;









share|improve this question



























  • 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 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











  • 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

















30


















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;









share|improve this question



























  • 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 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











  • 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













30













30









30


1






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;









share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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 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











  • 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

















  • 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 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











  • 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
















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












4 Answers
4






active

oldest

votes


















25



















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.






share|improve this answer



























  • 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


















18



















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.






share|improve this answer


































    5



















    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>








    share|improve this answer


































      3



















      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






      share|improve this answer


























        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
        );



        );














        draft saved

        draft discarded
















        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









        25



















        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.






        share|improve this answer



























        • 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















        25



















        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.






        share|improve this answer



























        • 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













        25















        25











        25









        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.






        share|improve this answer
















        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.







        share|improve this answer















        share|improve this answer




        share|improve this answer








        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

















        • 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













        18



















        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.






        share|improve this answer































          18



















          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.






          share|improve this answer





























            18















            18











            18









            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.






            share|improve this answer
















            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.







            share|improve this answer















            share|improve this answer




            share|improve this answer








            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
























                5



















                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>








                share|improve this answer































                  5



















                  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>








                  share|improve this answer





























                    5















                    5











                    5









                    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>








                    share|improve this answer
















                    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>






                    share|improve this answer















                    share|improve this answer




                    share|improve this answer








                    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
























                        3



















                        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






                        share|improve this answer





























                          3



















                          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






                          share|improve this answer



























                            3















                            3











                            3









                            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






                            share|improve this answer














                            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







                            share|improve this answer













                            share|improve this answer




                            share|improve this answer










                            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































                                draft saved

                                draft discarded















































                                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.




                                draft saved


                                draft discarded














                                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





















































                                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









                                Popular posts from this blog

                                Tamil (spriik) Luke uk diar | Nawigatjuun

                                Align equal signs while including text over equalitiesAMS align: left aligned text/math plus multicolumn alignmentMultiple alignmentsAligning equations in multiple placesNumbering and aligning an equation with multiple columnsHow to align one equation with another multline equationUsing \ in environments inside the begintabularxNumber equations and preserving alignment of equal signsHow can I align equations to the left and to the right?Double equation alignment problem within align enviromentAligned within align: Why are they right-aligned?

                                Where does the image of a data connector as a sharp metal spike originate from?Where does the concept of infected people turning into zombies only after death originate from?Where does the motif of a reanimated human head originate?Where did the notion that Dragons could speak originate?Where does the archetypal image of the 'Grey' alien come from?Where did the suffix '-Man' originate?Where does the notion of being injured or killed by an illusion originate?Where did the term “sophont” originate?Where does the trope of magic spells being driven by advanced technology originate from?Where did the term “the living impaired” originate?