5

I'm using a componentDidUpdate function

componentDidUpdate(prevProps){
     if(prevProps.value !== this.props.users){ 
        ipcRenderer.send('userList:store',this.props.users);    
}

to this

const users = useSelector(state => state.reddit.users)

    useEffect(() => {
       console.log('users changed')
       console.log({users})
    }, [users]);

but it I get the message 'users changed' when I start the app. But the user state HAS NOT changed at all

Sai Krishna
  • 547
  • 1
  • 12
  • 26

2 Answers2

6

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]);
Nicholas Tower
  • 72,740
  • 7
  • 86
  • 98
  • Thank you. This works. But when I use antoher useEffect for 'guest', it still fires on startup. Is there a solution? – Sai Krishna Jul 29 '19 at 15:43
  • 1
    If you find yourself needing to do this a lot, i recommend you extract the code to a custom hook. I've edited in an example of this. – Nicholas Tower Jul 29 '19 at 15:45
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.

Sultan H.
  • 2,908
  • 2
  • 11
  • 23