Search code examples
reactjsreact-hooksclosuresstate-saving

React useEffect cleanup function to save state to a database without running into closure probelms


I understand that this is an issue of closures. I have state in a reducer in my component, which, upon unmount, I would like to save to a database.

const [localState, dispatch] = useReducer(myReducer, initialState);

const handleUnmount = () => {
   saveToDB(localState);
}

useEffect(() => {
  return () => {
    handleUnmount()
  }
}, [])

When the component unmounts, the localState in the handleUnmount function is stale.

I tried wrapping handleUnmount in a useCallback with a dependency array which includes localState. I have tried putting localState in a useRef and referred to that in the handleUnmount function, but neither of the above work. Furthermore, if you include anything in the dependency array of the useEffect, then the handleUnmount function will run every time that value changes, instead of only on unmount, which is less than desirable behaviour. Is this possible at all in React? I will do anything to not have to include a "Save" button which must be explicitly clicked in order to save changes to the db...


Solution

  • Refs are the escape hatch to be used in such cases. They will always give the most updated and current value of any item, and do not need to be put into dependencies.

    You can use useRef to track the value.

    const [localState, dispatch] = useReducer(myReducer, initialState);
    const stateRef = useRef(localState);
    
    stateRef.current = localState;
    
    
    useEffect(() => {
      return () => {
         saveToDB(stateRef.current);
      }
    }, [])