Paul Trimor
Paul Trimor

Reputation: 340

Render component with async ComponentDidMount

I would like to create a <textarea> that behaves like console.log.

class Console extends Component {
...
    async componentDidMount() {
        for (var i = 1; i < 10; i++) {
           setTimeout(() => {this.setState({message: 'updateMessage' + millis()}, 1000);
        }
    }
    render() {
       return <textarea>{this.state.messsage}</textarea>
    }
}

I expected this code to update the UI in realtime. The issue is that componentDidMount waits until all the setTimeout's functions are executed in the loop then renders everything all at once.

Is there something I am misunderstanding? Thanks

Upvotes: 0

Views: 87

Answers (1)

Someone Special
Someone Special

Reputation: 13588

Your setTimeout are all resolved at the same time, and your messages are not in array, hence it's overwritten each time.

If I use a delay promise, instead of set timeout, then the state will be updated accordingly.

const delay = async () => {
  await new Promise((resolve) => {
    setTimeout(resolve, 1000)
})
}

Example: codesandbox

class Console extends Component {
...
    async componentDidMount() {
        for (var i = 1; i < 10; i++) {
           this.setState({message: 'updateMessage' + millis()})
           await delay()
        }
    }
    render() {
       return <textarea>{this.state.messsage}</textarea>
    }
}

Upvotes: 2

Related Questions