score:4

Accepted answer

Yep, that's how useEffect works. It runs after every render by default. If you supply an array as a second parameter, it will run on the first render, but then skip subsequent renders if the specified values have not changed. There is no built in way to skip the first render, since that's a pretty rare case.

If you need the code to have no effect on the very first render, you're going to need to do some extra work. You can use useRef to create a mutable variable, and change it to indicate once the first render is complete. For example:

  const isFirstRender = useRef(true);
  const users = useSelector(state => state.reddit.users);
  useEffect(() => {
    if (isFirstRender.current) {
      isFirstRender.current = false;
    } else {
       console.log('users changed')
       console.log({users})
    }
  }, [users]);

If you find yourself doing this a lot, you could create a custom hook so you can reuse it easier. Something like this:

const useUpdateEffect = (callback, dependencies) => {
  const isFirstRender = useRef(true);
  useEffect(() => {
    if (isFirstRender.current) {
      isFirstRender.current = false;
    } else {
      return callback();
    }

  }, dependencies);
}

// to be used like:

const users = useSelector(state => state.reddit.users);
useUpdateEffect(() => {
  console.log('users changed')
  console.log({users})
}, [users]);

score:0

If you’re familiar with React class lifecycle methods, you can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount combined.

As from: Using the Effect Hook

This, it will be invoked as the component is painted in your DOM, which is likely to be closer to componentDidMount.


Related Query

More Query from same tag