25 lines
881 B
TypeScript
25 lines
881 B
TypeScript
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];
|
|
}
|