Grant Herman
Grant Herman

Reputation: 973

useEffect to only update a specific key updates

I have a scenario where our application has multiple functions that sit within componentDidUpdate. In each of the functions they check to see if their specific data is updated. For example:

componentDidUpdate(prevProps) {
 this.handleFoo(prevProps)
 this.handleMoreFoo(prevProps)
}

handleFoo(prevProps){
  if(this.props.foo != prevProps.foo){
    //Do Something
 }
}

handleMoreFoo(prevProps){
  if(this.props.moreFoo != prevProps.moreFoo){
    //Do Something
 }
}

I have been looking at the useEffect hook and was wondering if I could chop out that initial check in each of these functions and utilize the [] in useEffect and only call one of these functions if their specific key is updated like this:

useEffect(() => {
   if(fooKey){ handleFoo() }
   if(moreFoo) { handleMoreFoo() }
 }, [fooKey, moreFooKey])

Is this possible? Is this advisable?

Upvotes: 1

Views: 1275

Answers (1)

Patrick Roberts
Patrick Roberts

Reputation: 51886

Here's how you'd accomplish what you had before, using hooks in a functional component.

I'd define a custom hook to mimic componentDidUpdate(), based on the answer to Make React useEffect hook not run on initial render:

function useUpdate (effect, deps) {
  const firstUpdate = useRef(true);
  const update = useCallback(() => {
    if (firstUpdate.current) {
      firstUpdate.current = false;
    } else {
      return effect();
    }
  }, [firstUpdate, effect]);

  useLayoutEffect(update, deps);
}

...

useUpdate(handleFoo, [fooKey]);
useUpdate(handleMoreFoo, [moreFooKey]);

useLayoutEffect() ensures that the handleX() callbacks are invoked at the same phase of each render as the analogous componentDidMount() and componentDidUpdate() lifecycle methods. If you don't care about the exact phase in which they're invoked, you can replace useLayoutEffect() with useEffect().

The rest of the custom hook ensures that it skips calling the handleX() callbacks after the initial render. If your handleX() callbacks can be called after the initial render, then you can just call useEffect() directly in your functional component instead of this useUpdate() custom hook.

Upvotes: 2

Related Questions