| import { useCallback, useEffect, useRef, useState } from 'react'; | |
| export function useStateCallback<T>( | |
| initialState: T | |
| ): [T, (state: T, cb?: (state: T) => void) => void] { | |
| const [state, setState] = useState(initialState); | |
| const cbRef = useRef<((state: T) => void) | undefined>(undefined); // init mutable ref container for callbacks | |
| const setStateCallback = useCallback((state: T, cb?: (state: T) => void) => { | |
| cbRef.current = cb; // store current, passed callback in ref | |
| setState(state); | |
| }, []); // keep object reference stable, exactly like `useState` | |
| useEffect(() => { | |
| // cb.current is `undefined` on initial render, | |
| // so we only invoke callback on state *updates* | |
| if (cbRef.current) { | |
| cbRef.current(state); | |
| cbRef.current = undefined; // reset callback after execution | |
| } | |
| }, [state]); | |
| return [state, setStateCallback]; | |
| } | |