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!