Understanding the React ‘useEffect’ hook and its practical applications

The second most frequently used hook in a React application for me is the useEffect hook. The primary use case of this hook is to perform automatic actions after the initial rendering of a React functional component.

The useEffect hook takes a callback function as the first argument and optionally takes an array as the second argument.

Approaches

We can use the useEffect hook in three ways: uncontrolled, loosely controlled, and tightly controlled. Regardless of the method you choose, the useEffect hook runs at least once after the initial rendering of a component.

Now, let's take a deeper dive into the approaches.

Uncontrolled

An uncontrolled useEffect hook runs every time a component is rendered. While it can be useful in some cases, it's usually recommended not to use an uncontrolled useEffect hook.

useEffect(() => {
  console.log('Effect hook ran');
});

The above code is an example of an uncontrolled useEffect hook. Notice that it doesn't take the second argument.

Loosely controlled

A loosely controlled useEffect hook runs only once after the initial rendering of a component. To achieve this behavior, we need to add an empty array as the second argument, as shown in the following example:

useEffect(() => {
  console.log('Effect hook ran');
}, []);

The above loosely controlled useEffect hook is useful when we want to execute some actions once, e.g., data fetching upon a component's initial rendering.

Tightly controlled

To make a useEffect hook tightly controlled, we need to add dependencies within the second argument array. By doing so, it tells React to run the useEffect hook only when at least one of these dependencies changes.

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

useEffect(() => {
  console.log('Effect hook ran');
}, [count]);

In the above example, we've added the count variable as a dependency within the second argument array. As a result, the useEffect hook runs every time the count variable changes.

Cleanup function

We can optionally return a cleanup function from the useEffect hook. By doing so, React will cancel any ongoing actions when a component re-renders or unmounts. While this is not always required, there are certain scenarios when it's necessary. Following is such an example.

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

useEffect(() => {
  const interval = setInterval(
    () => setCount((prevState) => prevState + 1),
    2000
  );

  return () => clearInterval(interval);
}, []);

In the above example, we've used the setInterval function to update the count state every two seconds. We've also returned a cleanup function where we clear the interval. As a result, React will cancel the interval when the component re-renders or unmounts.

The reasons we've used a cleanup function here are to avoid creating a new interval on each re-render and prevent the interval from running when the component is no longer in use. This is a performance optimization technique provided by the useEffect hook.

Applications

As mentioned before, we use the useEffect hook to perform automatic actions, e.g., data fetching, and updating states, in React functional components.

Today, we've standalone libraries for data fetching in React, and it's usually recommended not to use the useEffect hook for this purpose unless you have a specific use case. However, you will always use the useEffect hook to update the states in production React applications.

That's it for this one! I hope you've learned a thing or two about the React useEffect hook from this article. Writing some code and observing these behaviors will further solidify your learning. Happy coding!

Share this article with your friends

Copy URL

Elevate your JavaScript and freelance journey

Supercharge your JavaScript skills and freelance career. Subscribe now for expert tips and insights!