In React + TypeScript, I am trying to create a custom hook which returns stable updater function with referential types and stable signature such as those provenients from useState or useDispatch so that is not required in dependency arrays of hooks by the eslint rule hooks/exhaustive-deps
Here is an example:
import { useRef, useState, useEffect, useCallback } from 'react';
export type SetStateWithCallback<T> = React.SetStateAction<T> | ((newState: React.SetStateAction<T>, callback?: React.RefObject<Function>) => T);
export function useStateWithCallback<T>(initState: T): [T, React.Dispatch<SetStateWithCallback<T>>] {
const [state, setState] = useState<T>(initState);
const callbackRef = useRef<Function>(null);
const setStateWithCallback = useCallback((newState: React.SetStateAction<T>, callback?: React.RefObject<Function>) => {
callbackRef.current = typeof callback === 'function' ? callback : null;
setState(newState);
}, []);
useEffect(() => {
if (callbackRef.current) {
callbackRef.current?.(state);
callbackRef.current = null;
}
}, [state]);
return [state, setStateWithCallback];
}
But when using this custom hook, the eslint rule hooks/exhaustive-deps still requires the setStateWithCallback
to be included as a dependency, differently from what it does with the built-in setState
for example:
function MyTestComponent() {
const [state, setState] = useState({});
const [customState, setCustomState] = useStateWithCallback({});
const test = useCallback(() => setState({}), []); // Fine. No required dependency
const testCustom = useCallback(() => setCustomState({}), []); // Warning: React Hook useCallback has a missing dependency: 'setCustomState'. Either include it or remove the dependency array. eslint(hooks/exhaustive-deps)
return null;
}
How can I change setCustomState
to accomplish the same as setState
?