React :: issues with usePrevious

Viewed 34

So I've been struggling with the getting the well-known usePrevious hook properly for me. My particular problem is that I have a state whose value is computed using a hook, and I want to know the previous value of that state as well. The hook's return value changes based on its dependencies. A simplified example is given below (in actuality, my hook is looking at useUrlParams and useLocation hooks to compute its own result:

function usePrevious<T>(value: T): T | undefined {
  const ref = useRef<T>();
  useEffect(() => {
    ref.current = value;
  }, [value]);
  return ref.current;
}

function useGetCount() {
  const urlParams = useParams();
  const location = useLocation();
  return useCallback(() => { 
    // do something with urlParams and location and return a count
    return Math.random();
  }, [urlParams, location]);
}

const MyComponent: React.FC<{}> = () => {
  const getCount = useGetCount();
  const [count, setCount] = useState<number>();
  const prevCount = usePrevious(count);

  useEffect(() => { 
    const newValue = getCount();
    setCount(value => value === newValue ? value : newValue);
  }, [getCount]);

  useEffect(() => { 
    console.log(`${prevCount} -> ${count}`);
  }, [count, prevCount]);

  return null;
}

I'm expecting this code to print:

undefined -> 0.41999121265420203

However, the above code prints:

undefined -> undefined
undefined -> 0.41999121265420203

If I instead change the above code to:

  const [count, setCount] = useState<number>(getCount());

It prints:

undefined -> 0.4827576508527609
0.4827576508527609 -> 0.4486071253712367

If I initialize the state with a constant and remove the useEffect to update the state, I get a single console log as expected. But I wanna achieve the same result even if I've initialized the state with the result from another hook.

I understand WHY it's printing these values. What I wanna know is HOW I can change my code to catch a single state change event without checking for undefined of newValue === oldValue.

0 Answers
Related