tctco
tctco

Reputation: 65

React hooks: listen to only one state change but depend on several other states to update a new state?

I'm quite new to React and functional programming. I want to build a parent component that basically tells what the child component should render:

const Parent = (props) => {
  // blablabla...
  useEffect(() => {
    // blablabla...
    let newSomeOtherState = doSomething(stateThatFrequentlyChange, stateThatSeldomChange)
    setSomeOtherState(newSomeOtherState)
  }, [stateThatFrequentlyChange, stateThatSeldomChange])

  return <Child data={someOtherState} />
}

The problem is that I only want the parent component to listen to the stateThatSeldomChange and then update someOtherState based on the current stateThatFrequentlyChange.

If I remove stateThatFrequentlyChange, React would complain that React Hooks useEffect has missing dependencies....

How should I solve this warning?

Upvotes: 1

Views: 1254

Answers (1)

Dennis Vash
Dennis Vash

Reputation: 53974

In such case, common pattern is checking if the right argument triggered the useEffect, it can be achieved by comparing the current value with previous one via a reference:

const usePrevious = (arg, compareFn) => {
  const prevState = useRef();

  // Keep ref updated
  useEffect(() => {
    if (compareFn(prevStateSeldom.current, arg)) {
      prevState.current = arg;
    }
  }, [arg]);

  return prevStateSeldom.current;
};

const Parent = (props) => {
  const prevState = usePrevious(stateThatSeldomChange, Object.is);

  useEffect(() => {
    if (prevState !== stateThatSeldomChange) {
      setSomeOtherState(stateThatFrequentlyChange);
    }
  }, [stateThatFrequentlyChange, stateThatSeldomChange]);

  return <Child data={someOtherState} />;
};

This example follows common good practices and known assumptions (for more info see useEffect cases):

  • Each useEffect should have a single responsibility.
  • Hooks called in order, therefore you should extract the logic into custom hook for exposing variable into scope.

This logic commonly implemented by usePrevious hook, you can research receipts for it.

Upvotes: 1

Related Questions