Can I execute a function after setState is finished updating?

Solution 1:

setState(updater[, callback]) is an async function:

https://facebook.github.io/react/docs/react-component.html#setstate

You can execute a function after setState is finishing using the second param callback like:

this.setState({
    someState: obj
}, () => {
    this.afterSetStateFinished();
});

The same can be done with hooks in React functional component:

https://github.com/the-road-to-learn-react/use-state-with-callback#usage

Look at useStateWithCallbackLazy:

import { useStateWithCallbackLazy } from 'use-state-with-callback';

const [count, setCount] = useStateWithCallbackLazy(0);

setCount(count + 1, () => {
   afterSetCountFinished();
});

Solution 2:

render will be called every time you setState to re-render the component if there are changes. If you move your call to drawGrid there rather than calling it in your update* methods, you shouldn't have a problem.

If that doesn't work for you, there is also an overload of setState that takes a callback as a second parameter. You should be able to take advantage of that as a last resort.

Solution 3:

Making setState return a Promise

In addition to passing a callback to setState() method, you can wrap it around an async function and use the then() method -- which in some cases might produce a cleaner code:

(async () => new Promise(resolve => this.setState({dummy: true}), resolve)()
    .then(() => { console.log('state:', this.state) });

And here you can take this one more step ahead and make a reusable setState function that in my opinion is better than the above version:

const promiseState = async state =>
    new Promise(resolve => this.setState(state, resolve));

promiseState({...})
    .then(() => promiseState({...})
    .then(() => {
        ...  // other code
        return promiseState({...});
    })
    .then(() => {...});

This works fine in React 16.4, but I haven't tested it in earlier versions of React yet.

Also worth mentioning that keeping your callback code in componentDidUpdate method is a better practice in most -- probably all, cases.

Solution 4:

when new props or states being received (like you call setState here), React will invoked some functions, which are called componentWillUpdate and componentDidUpdate

in your case, just simply add a componentDidUpdate function to call this.drawGrid()

here is working code in JS Bin

as I mentioned, in the code, componentDidUpdate will be invoked after this.setState(...)

then componentDidUpdate inside is going to call this.drawGrid()

read more about component Lifecycle in React https://facebook.github.io/react/docs/component-specs.html#updating-componentwillupdate