React – things you should know about useEffect

Posted by

I have struggled with useEffect hook a couple of times recently. The reason why I struggled is mainly because useEffect covers the side effects of not only componentDidMount but also componentDidUpdate and componentWillUnmount. I come from class component based React, so it was very confusing at first.

The common misusages of useEffect hook can result in:

  • an infinite rendering of a component
  • not updating the target states
  • not rendering the components at all

Here are the three things you should know about useEffect.

  1. useEffect runs after the first paint, not before
  2. useEffect runs after value changes in dependencies
  3. Changes in both object and array states’ values cannot be detected

useEffect runs after the first paint

useEffect runs after the first paint. So, for example, if you plan to set state value to an array of items from null inside useEffect, the first render uses the state value null. Make sure that you will not try to iterate through the state value of null on the first paint.

const [list, setList] = useState(null);

useEffect(()=> {
    if(!list) {
        setList(['item1', 'item2']);
    }
}, []);

return (
    <ul>
    {
        /* make sure that list is not set to null */
        list && list.map(item => {

            return <li>{item}</li>;
        });
    }
    </ul>
);

useEffect runs after value changes in dependencies

The dependency array allows useEffect to run every time the values are updated. The code below will set your component in an infinite loop of rendering since count is set in the dependency array while being updated on every side effect.

const [count, setCount] = useState(0);

useEffect(() => {
    setCount(count + 1);
}, [count]);

Re-rendering components with object and array states

Use the ES6 spread operator ... to copy the existing items into the new array, and inserting the new item at the end. This way, React can detect changes in both object and array states by recognizing them as a new reference of object or array. Finally, the component re-renders by changes to the values of list in the dependency array.

// example for array state
const [list, setList] = useState(null);
const [updateCount, setUpdateCount] = useState(0);

const handleAddItem = (e) => {
    let item = e.target.value;
    setList([...list, item]);
}

useEffect(()=> {
    setUpdateCount(updateCount + 1);
}, [list]);

Thanks for reading.

Hope you enjoyed the article. If you have any question or opinion to share, feel free to write some comments.

Facebook Comments