React: potential race condition for Controlled Components












6















There is the following code in the React tutorial:



class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};

this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}

handleChange(event) {
this.setState({value: event.target.value});
}

handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}

render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}


There is also a warning about the setState method:




setState() does not always immediately update the component. It may
batch or defer the update until later. This makes reading this.state
right after calling setState() a potential pitfall.




Q: Is the following scenario possible:





  1. handleChange is fired;


  2. setState is queued in the React;


  3. handleSubmit is fired and it reads an obsolete value of this.state.value;


  4. setState is actually processed.


Or there is some kind of protection preventing such scenario from happening?










share|improve this question



























    6















    There is the following code in the React tutorial:



    class NameForm extends React.Component {
    constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleChange(event) {
    this.setState({value: event.target.value});
    }

    handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
    }

    render() {
    return (
    <form onSubmit={this.handleSubmit}>
    <label>
    Name:
    <input type="text" value={this.state.value} onChange={this.handleChange} />
    </label>
    <input type="submit" value="Submit" />
    </form>
    );
    }
    }


    There is also a warning about the setState method:




    setState() does not always immediately update the component. It may
    batch or defer the update until later. This makes reading this.state
    right after calling setState() a potential pitfall.




    Q: Is the following scenario possible:





    1. handleChange is fired;


    2. setState is queued in the React;


    3. handleSubmit is fired and it reads an obsolete value of this.state.value;


    4. setState is actually processed.


    Or there is some kind of protection preventing such scenario from happening?










    share|improve this question

























      6












      6








      6


      1






      There is the following code in the React tutorial:



      class NameForm extends React.Component {
      constructor(props) {
      super(props);
      this.state = {value: ''};

      this.handleChange = this.handleChange.bind(this);
      this.handleSubmit = this.handleSubmit.bind(this);
      }

      handleChange(event) {
      this.setState({value: event.target.value});
      }

      handleSubmit(event) {
      alert('A name was submitted: ' + this.state.value);
      event.preventDefault();
      }

      render() {
      return (
      <form onSubmit={this.handleSubmit}>
      <label>
      Name:
      <input type="text" value={this.state.value} onChange={this.handleChange} />
      </label>
      <input type="submit" value="Submit" />
      </form>
      );
      }
      }


      There is also a warning about the setState method:




      setState() does not always immediately update the component. It may
      batch or defer the update until later. This makes reading this.state
      right after calling setState() a potential pitfall.




      Q: Is the following scenario possible:





      1. handleChange is fired;


      2. setState is queued in the React;


      3. handleSubmit is fired and it reads an obsolete value of this.state.value;


      4. setState is actually processed.


      Or there is some kind of protection preventing such scenario from happening?










      share|improve this question














      There is the following code in the React tutorial:



      class NameForm extends React.Component {
      constructor(props) {
      super(props);
      this.state = {value: ''};

      this.handleChange = this.handleChange.bind(this);
      this.handleSubmit = this.handleSubmit.bind(this);
      }

      handleChange(event) {
      this.setState({value: event.target.value});
      }

      handleSubmit(event) {
      alert('A name was submitted: ' + this.state.value);
      event.preventDefault();
      }

      render() {
      return (
      <form onSubmit={this.handleSubmit}>
      <label>
      Name:
      <input type="text" value={this.state.value} onChange={this.handleChange} />
      </label>
      <input type="submit" value="Submit" />
      </form>
      );
      }
      }


      There is also a warning about the setState method:




      setState() does not always immediately update the component. It may
      batch or defer the update until later. This makes reading this.state
      right after calling setState() a potential pitfall.




      Q: Is the following scenario possible:





      1. handleChange is fired;


      2. setState is queued in the React;


      3. handleSubmit is fired and it reads an obsolete value of this.state.value;


      4. setState is actually processed.


      Or there is some kind of protection preventing such scenario from happening?







      javascript reactjs






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 15 '18 at 9:43









      Denis KulaginDenis Kulagin

      4,29663681




      4,29663681
























          2 Answers
          2






          active

          oldest

          votes


















          4














          I hope this
          answers your question:




          In React 16, if you call setState inside a React event handler, it is flushed when React exits the browser event handler. So it's not synchronous but happens in the same top-level stack.



          In React 16, if you call setState outside a React event handler, it is flushed immediately.




          Let's examine what happens (main points):




          1. entering handleChange react event handler;

          2. all setState calls are batched inside;

          3. exiting handleChange

          4. flushing setState changes


          5. render is called

          6. entering handleSubmit

          7. accessing correctly commited values from this.state

          8. exiting handleSubmit


          So as you see, race condition can't happen as long as updates are scheduled within React event handlers, since React commits all batched state updates in the end of every event handler call.






          share|improve this answer

































            3





            +50









            In your case reading old value is impossible. Under "It may batch or defer the update until later" it means just a case



            this.setState({a: 11});
            console.log(this.state.a);


            so setState may just add a change to queue but not directly update this.state. But it does not mean you can just change input with triggering handleChange and then click button triggering handleSubmit and .state is still not updated. It because how event loop works - if some code is executing browser will not process any event(you should experience cases when UI freezes for a while).



            So the only thing to reproduce 'race condition' is to run one handler from another:



            handleChange(event) {
            this.setState({value: event.target.value});
            this.handleSubmit();
            }


            This way, yes, you will get previous value shown in alert.



            For such a cases .setState takes optional callback parameter




            The second parameter to setState() is an optional callback function that will be executed once setState is completed and the component is re-rendered. Generally we recommend using componentDidUpdate() for such logic instead.




            Applied to your code it'd look like



            handleChange(event) {
            this.setState({value: event.target.value}, this.handleSubmit);
            }


            PS And sure your code may delay setState with setTimeout on your own like



            handleChange({target: {value}}) {
            setTimeout(() => {
            this.setState({value});
            }, 5000);
            }


            And there is no way to ensure handleSubmit is operating on latest value. But in such a case it's all on your shoulders how to handle that.



            [UPD] some details on how async works in JS. I have heard different terms: "event loop", "message queue", "microtask/task queue" and sometimes it means different things(and there is a difference actually). But to make things easier let's assume there is just single queue. And everything async like event handlers, Promise.then(), setImmediate() just go to the end of this queue.



            This way each setState(if it's in batch mode) does 2 things: adds changeset to stack(it could be array variable) and set up additional task into queue(say with setImmediate). This additional task will process all stacked changes and run rerender just once.



            Even if you would be so fast to click Submit button before those deferred updater is executed event handler would go to the end of queue. So event handler will definitely run after all batched state's changes are applied.



            Sorry, I cannot just refer to React code to prove because updater code looks really complex for me. But I found article that has many details how it works under the hood. Maybe it gives some additional information to you.



            [UPD] met nice article on microtasks, macrotasks and event loop: https://abc.danch.me/microtasks-macrotasks-more-on-the-event-loop-881557d7af6f?gi=599c66cc504c
            it does not change the result but makes me understand all that better






            share|improve this answer


























            • It became more clear to me, but not crystal yet. Do you say that React queues setState calls to some internal JS query that is guaranteed to be processed in between handling events?

              – Denis Kulagin
              Nov 18 '18 at 14:11













            • after reviewing my own answer I see it looks overcomplicated. So I've updated answer with more details.

              – skyboyer
              Nov 18 '18 at 20:03











            • Your and Karen answers are both great and I was having a hard time deciding whom to award the bounty. I have accepted Karen's answer for being more concise. But bounty goes to your answer as being much more detailed and containing useful references to investigate this issue in depth.

              – Denis Kulagin
              Nov 21 '18 at 8:05











            • found good article on microtask/macrotask/event loop: abc.danch.me/…

              – skyboyer
              Nov 29 '18 at 22:19











            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/3.0/"u003ecc by-sa 3.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%2f53316501%2freact-potential-race-condition-for-controlled-components%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            4














            I hope this
            answers your question:




            In React 16, if you call setState inside a React event handler, it is flushed when React exits the browser event handler. So it's not synchronous but happens in the same top-level stack.



            In React 16, if you call setState outside a React event handler, it is flushed immediately.




            Let's examine what happens (main points):




            1. entering handleChange react event handler;

            2. all setState calls are batched inside;

            3. exiting handleChange

            4. flushing setState changes


            5. render is called

            6. entering handleSubmit

            7. accessing correctly commited values from this.state

            8. exiting handleSubmit


            So as you see, race condition can't happen as long as updates are scheduled within React event handlers, since React commits all batched state updates in the end of every event handler call.






            share|improve this answer






























              4














              I hope this
              answers your question:




              In React 16, if you call setState inside a React event handler, it is flushed when React exits the browser event handler. So it's not synchronous but happens in the same top-level stack.



              In React 16, if you call setState outside a React event handler, it is flushed immediately.




              Let's examine what happens (main points):




              1. entering handleChange react event handler;

              2. all setState calls are batched inside;

              3. exiting handleChange

              4. flushing setState changes


              5. render is called

              6. entering handleSubmit

              7. accessing correctly commited values from this.state

              8. exiting handleSubmit


              So as you see, race condition can't happen as long as updates are scheduled within React event handlers, since React commits all batched state updates in the end of every event handler call.






              share|improve this answer




























                4












                4








                4







                I hope this
                answers your question:




                In React 16, if you call setState inside a React event handler, it is flushed when React exits the browser event handler. So it's not synchronous but happens in the same top-level stack.



                In React 16, if you call setState outside a React event handler, it is flushed immediately.




                Let's examine what happens (main points):




                1. entering handleChange react event handler;

                2. all setState calls are batched inside;

                3. exiting handleChange

                4. flushing setState changes


                5. render is called

                6. entering handleSubmit

                7. accessing correctly commited values from this.state

                8. exiting handleSubmit


                So as you see, race condition can't happen as long as updates are scheduled within React event handlers, since React commits all batched state updates in the end of every event handler call.






                share|improve this answer















                I hope this
                answers your question:




                In React 16, if you call setState inside a React event handler, it is flushed when React exits the browser event handler. So it's not synchronous but happens in the same top-level stack.



                In React 16, if you call setState outside a React event handler, it is flushed immediately.




                Let's examine what happens (main points):




                1. entering handleChange react event handler;

                2. all setState calls are batched inside;

                3. exiting handleChange

                4. flushing setState changes


                5. render is called

                6. entering handleSubmit

                7. accessing correctly commited values from this.state

                8. exiting handleSubmit


                So as you see, race condition can't happen as long as updates are scheduled within React event handlers, since React commits all batched state updates in the end of every event handler call.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 18 '18 at 23:24

























                answered Nov 18 '18 at 23:06









                Karen GrigoryanKaren Grigoryan

                3,05011023




                3,05011023

























                    3





                    +50









                    In your case reading old value is impossible. Under "It may batch or defer the update until later" it means just a case



                    this.setState({a: 11});
                    console.log(this.state.a);


                    so setState may just add a change to queue but not directly update this.state. But it does not mean you can just change input with triggering handleChange and then click button triggering handleSubmit and .state is still not updated. It because how event loop works - if some code is executing browser will not process any event(you should experience cases when UI freezes for a while).



                    So the only thing to reproduce 'race condition' is to run one handler from another:



                    handleChange(event) {
                    this.setState({value: event.target.value});
                    this.handleSubmit();
                    }


                    This way, yes, you will get previous value shown in alert.



                    For such a cases .setState takes optional callback parameter




                    The second parameter to setState() is an optional callback function that will be executed once setState is completed and the component is re-rendered. Generally we recommend using componentDidUpdate() for such logic instead.




                    Applied to your code it'd look like



                    handleChange(event) {
                    this.setState({value: event.target.value}, this.handleSubmit);
                    }


                    PS And sure your code may delay setState with setTimeout on your own like



                    handleChange({target: {value}}) {
                    setTimeout(() => {
                    this.setState({value});
                    }, 5000);
                    }


                    And there is no way to ensure handleSubmit is operating on latest value. But in such a case it's all on your shoulders how to handle that.



                    [UPD] some details on how async works in JS. I have heard different terms: "event loop", "message queue", "microtask/task queue" and sometimes it means different things(and there is a difference actually). But to make things easier let's assume there is just single queue. And everything async like event handlers, Promise.then(), setImmediate() just go to the end of this queue.



                    This way each setState(if it's in batch mode) does 2 things: adds changeset to stack(it could be array variable) and set up additional task into queue(say with setImmediate). This additional task will process all stacked changes and run rerender just once.



                    Even if you would be so fast to click Submit button before those deferred updater is executed event handler would go to the end of queue. So event handler will definitely run after all batched state's changes are applied.



                    Sorry, I cannot just refer to React code to prove because updater code looks really complex for me. But I found article that has many details how it works under the hood. Maybe it gives some additional information to you.



                    [UPD] met nice article on microtasks, macrotasks and event loop: https://abc.danch.me/microtasks-macrotasks-more-on-the-event-loop-881557d7af6f?gi=599c66cc504c
                    it does not change the result but makes me understand all that better






                    share|improve this answer


























                    • It became more clear to me, but not crystal yet. Do you say that React queues setState calls to some internal JS query that is guaranteed to be processed in between handling events?

                      – Denis Kulagin
                      Nov 18 '18 at 14:11













                    • after reviewing my own answer I see it looks overcomplicated. So I've updated answer with more details.

                      – skyboyer
                      Nov 18 '18 at 20:03











                    • Your and Karen answers are both great and I was having a hard time deciding whom to award the bounty. I have accepted Karen's answer for being more concise. But bounty goes to your answer as being much more detailed and containing useful references to investigate this issue in depth.

                      – Denis Kulagin
                      Nov 21 '18 at 8:05











                    • found good article on microtask/macrotask/event loop: abc.danch.me/…

                      – skyboyer
                      Nov 29 '18 at 22:19
















                    3





                    +50









                    In your case reading old value is impossible. Under "It may batch or defer the update until later" it means just a case



                    this.setState({a: 11});
                    console.log(this.state.a);


                    so setState may just add a change to queue but not directly update this.state. But it does not mean you can just change input with triggering handleChange and then click button triggering handleSubmit and .state is still not updated. It because how event loop works - if some code is executing browser will not process any event(you should experience cases when UI freezes for a while).



                    So the only thing to reproduce 'race condition' is to run one handler from another:



                    handleChange(event) {
                    this.setState({value: event.target.value});
                    this.handleSubmit();
                    }


                    This way, yes, you will get previous value shown in alert.



                    For such a cases .setState takes optional callback parameter




                    The second parameter to setState() is an optional callback function that will be executed once setState is completed and the component is re-rendered. Generally we recommend using componentDidUpdate() for such logic instead.




                    Applied to your code it'd look like



                    handleChange(event) {
                    this.setState({value: event.target.value}, this.handleSubmit);
                    }


                    PS And sure your code may delay setState with setTimeout on your own like



                    handleChange({target: {value}}) {
                    setTimeout(() => {
                    this.setState({value});
                    }, 5000);
                    }


                    And there is no way to ensure handleSubmit is operating on latest value. But in such a case it's all on your shoulders how to handle that.



                    [UPD] some details on how async works in JS. I have heard different terms: "event loop", "message queue", "microtask/task queue" and sometimes it means different things(and there is a difference actually). But to make things easier let's assume there is just single queue. And everything async like event handlers, Promise.then(), setImmediate() just go to the end of this queue.



                    This way each setState(if it's in batch mode) does 2 things: adds changeset to stack(it could be array variable) and set up additional task into queue(say with setImmediate). This additional task will process all stacked changes and run rerender just once.



                    Even if you would be so fast to click Submit button before those deferred updater is executed event handler would go to the end of queue. So event handler will definitely run after all batched state's changes are applied.



                    Sorry, I cannot just refer to React code to prove because updater code looks really complex for me. But I found article that has many details how it works under the hood. Maybe it gives some additional information to you.



                    [UPD] met nice article on microtasks, macrotasks and event loop: https://abc.danch.me/microtasks-macrotasks-more-on-the-event-loop-881557d7af6f?gi=599c66cc504c
                    it does not change the result but makes me understand all that better






                    share|improve this answer


























                    • It became more clear to me, but not crystal yet. Do you say that React queues setState calls to some internal JS query that is guaranteed to be processed in between handling events?

                      – Denis Kulagin
                      Nov 18 '18 at 14:11













                    • after reviewing my own answer I see it looks overcomplicated. So I've updated answer with more details.

                      – skyboyer
                      Nov 18 '18 at 20:03











                    • Your and Karen answers are both great and I was having a hard time deciding whom to award the bounty. I have accepted Karen's answer for being more concise. But bounty goes to your answer as being much more detailed and containing useful references to investigate this issue in depth.

                      – Denis Kulagin
                      Nov 21 '18 at 8:05











                    • found good article on microtask/macrotask/event loop: abc.danch.me/…

                      – skyboyer
                      Nov 29 '18 at 22:19














                    3





                    +50







                    3





                    +50



                    3




                    +50





                    In your case reading old value is impossible. Under "It may batch or defer the update until later" it means just a case



                    this.setState({a: 11});
                    console.log(this.state.a);


                    so setState may just add a change to queue but not directly update this.state. But it does not mean you can just change input with triggering handleChange and then click button triggering handleSubmit and .state is still not updated. It because how event loop works - if some code is executing browser will not process any event(you should experience cases when UI freezes for a while).



                    So the only thing to reproduce 'race condition' is to run one handler from another:



                    handleChange(event) {
                    this.setState({value: event.target.value});
                    this.handleSubmit();
                    }


                    This way, yes, you will get previous value shown in alert.



                    For such a cases .setState takes optional callback parameter




                    The second parameter to setState() is an optional callback function that will be executed once setState is completed and the component is re-rendered. Generally we recommend using componentDidUpdate() for such logic instead.




                    Applied to your code it'd look like



                    handleChange(event) {
                    this.setState({value: event.target.value}, this.handleSubmit);
                    }


                    PS And sure your code may delay setState with setTimeout on your own like



                    handleChange({target: {value}}) {
                    setTimeout(() => {
                    this.setState({value});
                    }, 5000);
                    }


                    And there is no way to ensure handleSubmit is operating on latest value. But in such a case it's all on your shoulders how to handle that.



                    [UPD] some details on how async works in JS. I have heard different terms: "event loop", "message queue", "microtask/task queue" and sometimes it means different things(and there is a difference actually). But to make things easier let's assume there is just single queue. And everything async like event handlers, Promise.then(), setImmediate() just go to the end of this queue.



                    This way each setState(if it's in batch mode) does 2 things: adds changeset to stack(it could be array variable) and set up additional task into queue(say with setImmediate). This additional task will process all stacked changes and run rerender just once.



                    Even if you would be so fast to click Submit button before those deferred updater is executed event handler would go to the end of queue. So event handler will definitely run after all batched state's changes are applied.



                    Sorry, I cannot just refer to React code to prove because updater code looks really complex for me. But I found article that has many details how it works under the hood. Maybe it gives some additional information to you.



                    [UPD] met nice article on microtasks, macrotasks and event loop: https://abc.danch.me/microtasks-macrotasks-more-on-the-event-loop-881557d7af6f?gi=599c66cc504c
                    it does not change the result but makes me understand all that better






                    share|improve this answer















                    In your case reading old value is impossible. Under "It may batch or defer the update until later" it means just a case



                    this.setState({a: 11});
                    console.log(this.state.a);


                    so setState may just add a change to queue but not directly update this.state. But it does not mean you can just change input with triggering handleChange and then click button triggering handleSubmit and .state is still not updated. It because how event loop works - if some code is executing browser will not process any event(you should experience cases when UI freezes for a while).



                    So the only thing to reproduce 'race condition' is to run one handler from another:



                    handleChange(event) {
                    this.setState({value: event.target.value});
                    this.handleSubmit();
                    }


                    This way, yes, you will get previous value shown in alert.



                    For such a cases .setState takes optional callback parameter




                    The second parameter to setState() is an optional callback function that will be executed once setState is completed and the component is re-rendered. Generally we recommend using componentDidUpdate() for such logic instead.




                    Applied to your code it'd look like



                    handleChange(event) {
                    this.setState({value: event.target.value}, this.handleSubmit);
                    }


                    PS And sure your code may delay setState with setTimeout on your own like



                    handleChange({target: {value}}) {
                    setTimeout(() => {
                    this.setState({value});
                    }, 5000);
                    }


                    And there is no way to ensure handleSubmit is operating on latest value. But in such a case it's all on your shoulders how to handle that.



                    [UPD] some details on how async works in JS. I have heard different terms: "event loop", "message queue", "microtask/task queue" and sometimes it means different things(and there is a difference actually). But to make things easier let's assume there is just single queue. And everything async like event handlers, Promise.then(), setImmediate() just go to the end of this queue.



                    This way each setState(if it's in batch mode) does 2 things: adds changeset to stack(it could be array variable) and set up additional task into queue(say with setImmediate). This additional task will process all stacked changes and run rerender just once.



                    Even if you would be so fast to click Submit button before those deferred updater is executed event handler would go to the end of queue. So event handler will definitely run after all batched state's changes are applied.



                    Sorry, I cannot just refer to React code to prove because updater code looks really complex for me. But I found article that has many details how it works under the hood. Maybe it gives some additional information to you.



                    [UPD] met nice article on microtasks, macrotasks and event loop: https://abc.danch.me/microtasks-macrotasks-more-on-the-event-loop-881557d7af6f?gi=599c66cc504c
                    it does not change the result but makes me understand all that better







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Nov 29 '18 at 22:19

























                    answered Nov 18 '18 at 9:00









                    skyboyerskyboyer

                    3,88811229




                    3,88811229













                    • It became more clear to me, but not crystal yet. Do you say that React queues setState calls to some internal JS query that is guaranteed to be processed in between handling events?

                      – Denis Kulagin
                      Nov 18 '18 at 14:11













                    • after reviewing my own answer I see it looks overcomplicated. So I've updated answer with more details.

                      – skyboyer
                      Nov 18 '18 at 20:03











                    • Your and Karen answers are both great and I was having a hard time deciding whom to award the bounty. I have accepted Karen's answer for being more concise. But bounty goes to your answer as being much more detailed and containing useful references to investigate this issue in depth.

                      – Denis Kulagin
                      Nov 21 '18 at 8:05











                    • found good article on microtask/macrotask/event loop: abc.danch.me/…

                      – skyboyer
                      Nov 29 '18 at 22:19



















                    • It became more clear to me, but not crystal yet. Do you say that React queues setState calls to some internal JS query that is guaranteed to be processed in between handling events?

                      – Denis Kulagin
                      Nov 18 '18 at 14:11













                    • after reviewing my own answer I see it looks overcomplicated. So I've updated answer with more details.

                      – skyboyer
                      Nov 18 '18 at 20:03











                    • Your and Karen answers are both great and I was having a hard time deciding whom to award the bounty. I have accepted Karen's answer for being more concise. But bounty goes to your answer as being much more detailed and containing useful references to investigate this issue in depth.

                      – Denis Kulagin
                      Nov 21 '18 at 8:05











                    • found good article on microtask/macrotask/event loop: abc.danch.me/…

                      – skyboyer
                      Nov 29 '18 at 22:19

















                    It became more clear to me, but not crystal yet. Do you say that React queues setState calls to some internal JS query that is guaranteed to be processed in between handling events?

                    – Denis Kulagin
                    Nov 18 '18 at 14:11







                    It became more clear to me, but not crystal yet. Do you say that React queues setState calls to some internal JS query that is guaranteed to be processed in between handling events?

                    – Denis Kulagin
                    Nov 18 '18 at 14:11















                    after reviewing my own answer I see it looks overcomplicated. So I've updated answer with more details.

                    – skyboyer
                    Nov 18 '18 at 20:03





                    after reviewing my own answer I see it looks overcomplicated. So I've updated answer with more details.

                    – skyboyer
                    Nov 18 '18 at 20:03













                    Your and Karen answers are both great and I was having a hard time deciding whom to award the bounty. I have accepted Karen's answer for being more concise. But bounty goes to your answer as being much more detailed and containing useful references to investigate this issue in depth.

                    – Denis Kulagin
                    Nov 21 '18 at 8:05





                    Your and Karen answers are both great and I was having a hard time deciding whom to award the bounty. I have accepted Karen's answer for being more concise. But bounty goes to your answer as being much more detailed and containing useful references to investigate this issue in depth.

                    – Denis Kulagin
                    Nov 21 '18 at 8:05













                    found good article on microtask/macrotask/event loop: abc.danch.me/…

                    – skyboyer
                    Nov 29 '18 at 22:19





                    found good article on microtask/macrotask/event loop: abc.danch.me/…

                    – skyboyer
                    Nov 29 '18 at 22:19


















                    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%2f53316501%2freact-potential-race-condition-for-controlled-components%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

                    Xamarin.iOS Cant Deploy on Iphone

                    Glorious Revolution

                    Dulmage-Mendelsohn matrix decomposition in Python