The basic case

function App() {
  const [count, setCount] = useState(0);

  const handleClick = () = > {
    setCount(2);
    func(); // Press to print 0
  };

  const func = () = > {
    console.log(count);
  };

  return (
    <div className="App">
      <button onClick={handleClick}>Click on the</button>
    </div>
  );
}
Copy the code

When we click the button, the console prints the last value, 0, instead of the latest value, 2

In order to reduce the number of render times, React collects all state changes, compares the optimization, and finally makes a change. Func calls and setCount are in the same macro task as react. So if you just use count to get the value 0 from the last closure

Yes, this is a solution, but sometimes there is more than one state to be passed. Again, because of react-hooks, So I chose to implement custom hooks to get the latest values immediately after useState changes. Let’s look at the implementation. The code changes are as follows:

function App() {
  const [count, setCount] = useState(0);

  const handleClick = () = > {
    setstate(2);
    func(); / / print 2
  };
  /** Passes the func method to useSyncCallback and returns a new function */
  const func = useSyncCallback(() = > {
    console.log(count);
  });

  return (
    <div className="App">
       <button onClick={handleClick}>Click on the</button>
    </div>
  );
}

export default App;

Copy the code

How to implement useSyncCallback?

import { useEffect, useState, useCallback } from 'react';

const useSyncCallback = callback= > {
    const [proxyState, setProxyState] = useState({ current: false });

    const Func = useCallback(() = > {
        setProxyState({ current: true });
    }, [proxyState])

    useEffect(() = > {
        if (proxyState.current === true) setProxyState({ current: false });
    }, [proxyState])

    useEffect(() = > {
        proxyState.current && callback();
    })

    return Func
}

export default useSyncCallback;
Copy the code