To carry out side effects, for example, working directly with the DOM in React, we use the built-in useEffect()
. It replaces three life cycle callbacks:
componentDidMount()
componentDidUpdate()
componentWillUnmount()
If you forgot or didn't know how they work, then you can read more about it in the official documentation.
Let's start with a simple example:
import React, { useState, useEffect } from 'react';
const Example = () => {
const [count, setCount] = useState(0);
// Works like componentDidMount and componentDidUpdate combined
// Starts after rendering the component
// Called after each click on the button
useEffect(() => {
// The state is accessible internally, as the scope is normal
alert(`Clicks ${count}`);
});
// With classes, we'd do this
// Note the duplication
// componentDidMount() {
// alert(`Clicks: ${count}`);
// }
// componentDidUpdate() {
// alert(`Clicks: ${count}`);
// }
return (
<div>
<p>You clicked {count} time(s)</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
};
Below is an example in which the background changes with each click.
The callback passed to useEffect()
is processed after the component's first rendering, and after each update. In othe words, the componentDidUpdate()
and componentDidMount()
methods were combined. This change was made for convenience. Worldwide practice using React has shown that, essentially, effects occur after each render, regardless of whether this is the first rendering or subsequent ones. As a bonus, the amount of duplication and code has been reduced. What are typical side effects found in the frontend? For example:
The action of the useEffect()
hook can sometimes be skipped. This can be useful either for optimization purposes, or if the effect is only of use under certain conditions. To do this, an array of values that must be tracked between renderings is passed to the hook as the second argument. If at least one value from this array has changed, the callback is called, if all values remain the same, it is skipped.
useEffect(() => {
alert(`Clicks ${count}`);
}, [count]);
// Equivalent
componentDidUpdate(prevProps, prevState) {
if (prevState.count !== this.state.count) {
alert(`Clicks ${count}`);
}
}
I.e., the callback will be called only when the count
changes. In the same way, you can pass any set of variables that we'd like to associate with the effect change. If at least one variable in the passed array has changed, the effect will work, otherwise React will skip it.
What should I do if I need to run useEffect()
only when the first render occurs (immediately after mounting)? To do this, you just need to pass an empty array:
// Replaces componentDidMount
useEffect(() => {
alert(`Clicks ${count}`);
}, []);
This solution isn't the most obvious, but technically, it's not a special case. You just need to get used to it.
In some cases, the effect needs to be reset. For example, when the effect after changing the props ceases to be relevant, it needs to be "cleaned up". To do this, you just need to return the function from useEffect()
, and the cleanup is carried out inside.
// Let's assume that this effect depends on the userId prop
useEffect(() => {
const id = setTimeout(/* some code with userId */);
return () => clearTimeout(id);
}, [userId]);
Changing the userId will reset the current timer and install a new one. This kind of code in classes would require the use of as many as 4 life cycle callbacks.
To simulate componentWillUnmount()
just connect the cleanup to an empty array with a second parameter:
useEffect(() => {
return () => {
// This logic will be executed only when the component is unmounted
};
}, []);
The Hexlet support team or other students will answer you.
A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.
Programming courses for beginners and experienced developers. Start training for free
Our graduates work in companies:
From a novice to a developer. Get a job or your money back!
Sign up or sign in
Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.