0

here is the code sample :


class App extends Component {
  constructor() {
    super();
    this.state = {
      currentColor: "red"
    };

    while(1){
   await this.changeColor();
    }
  }

  changeColor = async () => {
    console.log("123")
     setTimeout(() => {
      this.setState({
        currentColor: "yellow"
      });
      setTimeout(() => {
        this.setState({
          currentColor: "green"
        });
        setTimeout(() => {
          this.setState({
            currentColor: "red"
          });
        }, 100);
      }, 200);
    }, 300);
  };

  render() {
    return (
      <div>
        <div
          className={this.state.currentColor}
          style={{ width: "100px", height: "100px" }}
        />
      </div>
    );
  }
}

when I add await in front of changeColor() , I got an ''Unexpected strict mode reserved word' error. the online code:https://stackblitz.com/edit/react-cm4jdq. (I want to right an traffic lights demo)

jjzjx118_2
  • 419
  • 7
  • 23

1 Answers1

0

You can only use await in the context of an async function. constructor is not async, hence the error. The constructor cannot be declared async because the constructor must return the constructed object, and an async function returns a promise.

The good news is there's no need for changeColor to be async and no need to await it in a never-ending while loop. If you want it to run continuously, use setInterval instead of setTimeout.

I'd also suggest that you cycle through an array of colors instead of repeating setTimeout/setState for each.


const classnames = ['yellow', 'green', 'red'];

function App () {
  const [colorIndex, setColorIndex] = React.useState(0);

  React.useEffect(() => {
    const interval = setInterval(() => {
      this.setState({
        colorIndex: (colorIndex + 1) % colors.length
      }), 100);
    });

    // cancel interval on unmount
    return () => clearInterval(interval);
  }, [])

  return <div className={classnames[colorIndex]}> ... </div>
}
ray
  • 26,557
  • 5
  • 28
  • 27
  • I guess that a traffic light wouldn't switch between green, yellow and red in always the same interval of `100ms`. Also you are immediately clearing the interval instead of returning a function that does so. – trixn Jul 20 '20 at 07:11
  • thank you, but since setTimeout is async. how can I combine await and setTimeout? I want to execute the next loop after setTimeout finished. – jjzjx118_2 Jul 20 '20 at 07:12
  • oh, I just found I can add this.changeColor() inside the innermostTimeout function, and also I think your solution is more graceful. thank you so much – jjzjx118_2 Jul 20 '20 at 07:16
  • setTimeout is not async in the way that you mean. Yes, it's asynchronous, but not in the async/await sense. It does not return a promise and you can't await it. – ray Jul 20 '20 at 15:14
  • Oops. The clearTimeout call was supposed to be a cleanup function for the effect rather than calling it immediately. Fixed. – ray Jul 20 '20 at 15:14