codegino
← all posts

React useEffect Hook

An introduction on how to use useEffect Hook in your React application

3 min read#react#tech

ripple effect
ripple effect

What is a useEffect Hook?

TL;DR

React useEffect is an alternative to the "old" class lifecycle methods/hooks. It is used to manage side effects, such as network requests or run a piece of code when the component is mounted, updated, or unmounted.

Longer version

Before React v16.8, we can only enable a component to react to state changes using lifecycle methods.

How to define a useEffect

.jsx
1useEffect(() => { //(1) declaration2  // (2)effect3  return () => {4    // (3)cleanup 5  }6}, /* (4)dependency array */)

Here's a quick explanation of the above code:

  1. We can declare an effect by calling either React.useEffect or useEffect.
  2. effect is the function that will be called when the component is mounted. OR when the dependency array changes.
  3. cleanup is the function called when the effect is "unmounted".
  4. dependency array is the array of values passed as a second argument to the effect function.
    • If there is no dependency array, the effect will be called every time the component is mounted.
    • If the array is empty, the effect will be called only once when the component is mounted.
    • If the array is not empty, the effect will be called every time the component is mounted and the dependency array changes.

Examples


Increment a counter every second until it reaches 10

.jsx
1function App() {2  const [count, setCount] = useState(0)3
4  useEffect(() => {5    if (count < 10) {6      const interval = setInterval(() => {7        setCount(prev => prev + 1)8      }, 1000)9
10      // cleanup function11      return () => clearInterval(interval)12    }13  }, [count])14
15  // Render the component16}
Open in CodePen ↗

Basic fetch from an API

.jsx
1function App() {2  const [data, setData] = useState([])3
4  useEffect(() => {5    fetch('https://jsonplaceholder.typicode.com/users')6      .then(res => res.json())7      .then(data => setData(data))8  }, [])9
10  // Render the component11}
Open in CodePen ↗

Fetching with loading indicator + error handling - then/catch/finally

.jsx
1function App() {2  const [data, setData] = React.useState()3  const [error, setError] = React.useState()4  const [isLoading, setIsLoading] = React.useState(false)5
6  React.useEffect(() => {7    setIsLoading(true)8
9    fetchData()10      .then(data => {11        setError(null)12        setData(data)13      })14      .catch(data => {15        // handle error case anyway you want16        setError(data)17        setData(null)18      })19      .finally(() => setIsLoading(false))20  }, [])21
22  // Render the component23}
Open in CodePen ↗

Fetching with loading indicator + error handling - async/await

.jsx
1function App() {2  const [data, setData] = React.useState()3  const [error, setError] = React.useState()4  const [isLoading, setIsLoading] = React.useState(false)5
6  React.useEffect(() => {7    // yeah, this is weird8    (async () => {9      try {10        setIsLoading(true)11        const data = await fetchData()12        setError(null)13        setData(data)14      } catch(e) {15        // handle error case anyway you want16        setError(e)17        setData(null)18      }19      setIsLoading(false)20    })()21  }, [])22
23  // Render the component24}
Open in CodePen ↗

Store a value in localStorage everytime the key or value changes

.jsx
1function App({ name }) {2  const [value, setValue] = useState(() => localStorage.getItem(name))3
4  useEffect(() => {5    localStorage.setItem(name, value)6  }, [name, value])7  // Ignore old keys for now8
9  // Render the component10}
Open in CodePen ↗

OR mimic a class lifecycle method

Check this blog on how to convert a class lifecycle methods to useEffect hooks


Additional Note

  • useEffect can only be used in functional components
  • The order of useEffect declarations is important.
  • useEffect in a custom hook is a great way to promote side effect reusability. I will discuss this in another blog.

Conclusion

Compared to the old lifecycle methods, useEffect is much more powerful and flexible, making it an ideal choice when managing a side-effect.