Search code examples
reactjsreact-hooks

How to compare oldValues and newValues on React Hooks useEffect?


Let's say I have 3 inputs: rate, sendAmount, and receiveAmount. I put that 3 inputs on useEffect diffing params. The rules are:

  • If sendAmount changed, I calculate receiveAmount = sendAmount * rate
  • If receiveAmount changed, I calculate sendAmount = receiveAmount / rate
  • If rate changed, I calculate receiveAmount = sendAmount * rate when sendAmount > 0 or I calculate sendAmount = receiveAmount / rate when receiveAmount > 0

Here is the codesandbox https://codesandbox.io/s/pkl6vn7x6j to demonstrate the problem.

Is there a way to compare the oldValues and newValues like on componentDidUpdate instead of making 3 handlers for this case?

Thanks


Here is my final solution with usePrevious https://codesandbox.io/s/30n01w2r06

In this case, I cannot use multiple useEffect because each change is leading to the same network call. That's why I also use changeCount to track the change too. This changeCount also helpful to track changes from local only, so I can prevent unnecessary network call because of changes from the server.


Solution

  • You can write a custom hook to provide you a previous props using useRef

    function usePrevious(value) {
      const ref = useRef();
      useEffect(() => {
        ref.current = value;
      });
      return ref.current;
    }
    

    and then use it in useEffect

    const Component = (props) => {
        const {receiveAmount, sendAmount } = props
        const prevAmount = usePrevious({receiveAmount, sendAmount});
        useEffect(() => {
            if(prevAmount.receiveAmount !== receiveAmount) {
    
             // process here
            }
            if(prevAmount.sendAmount !== sendAmount) {
    
             // process here
            }
        }, [receiveAmount, sendAmount])
    }
    

    However its clearer and probably better and clearer to read and understand if you use two useEffect separately for each change id you want to process them separately