React hooks: accessing up-to-date state from within a callback

后端 未结 8 1711
梦谈多话
梦谈多话 2020-12-25 09:35

EDIT (22 June 2020): as this question has some renewed interest, I realise there may be a few points of confusion. So I would like to highlight: the example in the question

8条回答
  •  醉梦人生
    2020-12-25 10:14

    Instead of trying to access the most recent state within a callback, use useEffect. Setting your state with the function returned from setState will not immediately update your value. The state updates are batched and updated

    It may help if you think of useEffect() like setState's second parameter (from class based components).

    If you want to do an operation with the most recent state, use useEffect() which will be hit when the state changes:

    const {
      useState,
      useEffect
    } = React;
    
    function App() {
      const [count, setCount] = useState(0);
      const decrement = () => setCount(count-1);
      const increment = () => setCount(count+1);
      
      useEffect(() => {
        console.log("useEffect", count);
      }, [count]);
      console.log("render", count);
      
      return ( 
        

    {count}

    ); } const rootElement = document.getElementById("root"); ReactDOM.render( < App / > , rootElement);
    
    
    
    

    Update

    You can create a hook for your setInterval and call it like this:

    const {
      useState,
      useEffect,
      useRef
    } = React;
    
    function useInterval(callback, delay) {
      const savedCallback = useRef();
    
      // Remember the latest callback.
      useEffect(() => {
        savedCallback.current = callback;
      }, [callback]);
    
      // Set up the interval.
      useEffect(() => {
        function tick() {
           savedCallback.current();
        }
        if (delay !== null) {
          let id = setInterval(tick, delay);
          return () => clearInterval(id);
        }
      }, [delay]);
    }
    
    
    function Card(title) {
      const [count, setCount] = useState(0);
      const callbackFunction = () => { 
        console.log(count);
      };
      useInterval(callbackFunction, 3000); 
      
      useEffect(()=>{
        console.log('Count has been updated!');
      }, [count]); 
      
      return (
    Active count {count}
    ); } const el = document.querySelector("#root"); ReactDOM.render(, el);
    
    
    
    

    Some further info on useEffect()

提交回复
热议问题