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]);