Skip to content

Instantly share code, notes, and snippets.

@zinozzino
Created May 14, 2020 09:04
Show Gist options
  • Save zinozzino/53153c7f2d7880514807a8417cfb2bcb to your computer and use it in GitHub Desktop.
Save zinozzino/53153c7f2d7880514807a8417cfb2bcb to your computer and use it in GitHub Desktop.
useDerivedState hook
import {
useRef,
useEffect,
useState,
Dispatch,
SetStateAction,
} from 'react';
const noop = () => {
return undefined;
};
const isEqual = <T>(a: T, b: T) => a === b;
export function useDerivedState<T>(
prop: T,
onChange: (newProp: T) => void = noop,
predicate: (a: T, b: T) => boolean = isEqual
): [T, Dispatch<SetStateAction<T>>] {
const [state, setState] = useState(() => prop);
const prevProp = useRef(prop);
const ref = useRef(state);
const isPropChanged = !predicate(prevProp.current, prop);
const isStateChanged = !predicate(ref.current, state);
useEffect(() => {
ref.current = state;
if (!isPropChanged) {
onChange(state);
}
}, [isPropChanged, state]);
useEffect(() => {
if (!isStateChanged && isPropChanged) {
setState(prop);
}
prevProp.current = prop;
}, [isStateChanged, isPropChanged, prop]);
return [state, setState];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment