Pairing A Callback With A useState Hook

React's Class-based state management allowed you to update the state of your component with a call to this.setState(). The first argument represents the changes to the state. It also accepts a second argument; a callback that will be invoked after the state has been updated.

this.setState({ loading: true }, () => console.log("Loading..."));

If you've transitioned to Hooks-based state management, then you may have noticed that the updaters generated by useState calls do not accept a second callback argument.

If you want to update state and fire a callback in response to it, you can pair useState with useEffect.

import React, { useState, useEffect } from "react";

function App() {
  const [loading, setLoading] = useState(false);
  const toggleLoading = () => setLoading(prevLoading => !prevLoading);
  useEffect(() => {
    if(loading) {
      console.log("We are loading now");
    }
  }, [loading])

  return (
    <div>
      {loading && <p>Loading...</p>}
      <button onClick={toggleLoading}>{loading ? "Cancel" : "Save"}</button>
    </div>
  );
}

The useState acts on its own. It has no side-effects. We follow it with a useEffect that responds to changes to the value of loading -- this is where our callback gets invoked.

See a live example.

Last updated