DEV Community

adelchms96
adelchms96

Posted on

react hook for waiting state update (useAsyncState)

hello guys, React is an awesome library especially after introducing hooks in function component which help us minimize the code writing already written in class components, but this didn't change how react work especially state update which happen asynchronous.
So image we want to invoke a function on each state update, we need to invoke it from useEffect like this example:

function App() {
  const [state, setState] = useState(0);
useEffect(()=>{
console.log(state);
},[state])
  return (
    <button onClick={()=>setState(prev => prev + 1)}>
      {state}
      increment
    </button>
  );
}
Enter fullscreen mode Exit fullscreen mode

but why we can't have to wait for set update to happen then invoke our function like this:

 const currentState = await setState(prev => prev + 1);
 console.log(currentState);
Enter fullscreen mode Exit fullscreen mode

this what useAsyncState come for have a look at the code:

import { useState, useRef, useCallback, useEffect } from "react";

function useAsyncState(initialState) {
  const [state, setState] = useState(initialState);
  const resolveState = useRef();
  const isMounted = useRef(false);

  useEffect(() => {
    isMounted.current = true;

    return () => {
      isMounted.current = false;
    };
  }, []);

  useEffect(() => {
    if (resolveState.current) {
      resolveState.current(state);
    }
  }, [state]);

  const setAsyncState = useCallback(
    newState =>
      new Promise(resolve => {
        if (isMounted.current) {
          resolveState.current = resolve;
          setState(newState);
        }
      }),
    []
  );

  return [state, setAsyncState];
}

export default useAsyncState;
Enter fullscreen mode Exit fullscreen mode

usage no need for the useEffect anymore :

function App() {
  const [state, setState] = useAsyncState(0);
  const click = async () => {
    const currentState = await setState(prev => prev + 1);
    console.log(currentState);
  };
  return (
    <button onClick={click}>
      {state}
      increment
    </button>
  );
}

Enter fullscreen mode Exit fullscreen mode

Top comments (0)