skip to Main Content

I have technical question about React render and await.

If I have a component that has a props called "label" that is used to set the text of a <p>, if I press a button that calls an async function that set a timeout of 10 seconds, what happens if the props "label" is changed while the timeout is still active?
The <p> value will be updated anyway? Or it will happen after the timeout is finished?
In other words, is a component locked while there is an active await?

I can produce an example if it can makes the question more clear.

import { Component } from "react";

export default class TestAsyncComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      label: "BEFORE",
    };
  }

  startAsync = async () => {
    console.log("START ASYNC");
    console.log(await this.foo());
  };

  foo = () => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("PROMISE FINISHED");
      }, 5000);
    });
  };

  changeLabel = () => {
    this.setState({ label: "AFTER" }, () => {
      console.log("LABEL CHANGED");
    });
  };

  render() {
    return (
      <div>
        <p>{this.state.label}</p>
        <button
          style={{ width: "100px", height: "50px" }}
          onClick={this.startAsync}
        >
          {"START ASYNC"}
        </button>
        <button
          style={{ width: "100px", height: "50px" }}
          onClick={this.changeLabel}
        >
          {"CHANGE LABEL"}
        </button>
      </div>
    );
  }
}

If I press the START ASYNC button and immediately after that the CHANGE LABEL button (while the await is still active) the label is changed.
My question is now more like: why this happen? Since javascript is single thread, how the await is handled if it doesn’t lock the component?

2

Answers


  1. It is not locked while there is an active await, the value will be updated anyway. EDIT: you can see it here https://react.dev/learn/state-as-a-snapshot scroll down, there is an example with this. EDIT2: Link I provided is react documentation on this and there is an example and explanation why this happens, just after example of this it says "The state stored in React may have changed by the time the alert runs, but it was scheduled using a snapshot of the state at the time the user interacted with it!"

    Login or Signup to reply.
  2. how the await is handled if it doesn’t lock the component?

    Why would it? Nothing is awaiting the call to startAsync(). (Nor should it.)

    When you click the button to invoke startAsync (and the button doesn’t and shouldn’t await that call), the asynchronous operation is started and the setTimeout is invoked. None of this is blocking, so control is returned to the UI immediately.

    When you click the button to invoke changeLabel, it updates state and logs to the console.

    Moments later, when the timeout has finished, the function passed to setTimeout executes which logs to the console.

    Nothing blocking is happening here, nor should it be.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search