In React, effects are actions in functional components that can influence components outside the pure rendering function and do not impact the rendering outcome. These can include working with APIs, changing the DOM, managing subscriptions, or setting timers.
useEffect runs effects after the component has rendered, allowing DOM updates, network requests, etc. without affecting the output of the component.
useEffect in React is used in cases like:
.webp)
useEffect takes two arguments:
If the array is empty, the effect will only run once after the initial rendering -- check out the following code snippet:
If the dependency array contains data and one of these values changes, the effect will be re-triggered after the component updates:
In some cases, it's necessary to clean up the effects. For example, when an effect is no longer relevant after the props have changed, it needs to be “cleaned up.” To achieve this, you simply return a function from the useEffect hook, within which the cleanup activities are performed -- check out the following code snippet:
This trick works great for all kinds of functions, not just React effects!
To fetch data from an API, asynchronous operations are necessary. However, useEffect does not support async functions directly.
We have several options to perform asynchronous operations.
— Defining an async function FetchData inside useEffect:
This is the most common and straightforward way to handle asynchronous operations inside useEffect.
— Using IIFE (Immediately Invoked Function Expression):
This approach is similar to the first one but uses an IIFE for the immediate invocation of an async function.
— Create an asynchronous function outside the body of useEffect and then call it inside useEffect:
This async approach can be particularly useful when the same function is used in multiple effects or in other parts of your component. However, it's important to remember that if your function depends on props or state of the component, these dependencies must be properly managed to avoid outdated closures.
Create your own hooks using useEffect to reuse complex effect logic across different components.
Then you can use it from any component like this:

Forgetting about dependencies:
A common mistake is not including all necessary dependencies in the effect's dependency array. This can lead to outdated data or infinite loops.
Best practice: Always include in the dependency array all values from the component's scope that are used in the effect and can change.
Using asynchronous functions directly in useEffect:
This can lead to warnings in the console because useEffect is not designed to work with promises directly.
Best practice: Wrap asynchronous operations in functions and call them inside the body of useEffect.
Creating unnecessary re-renders:
Due to incorrect definition of dependencies, your component may re-render more often than necessary.
Best practice: Carefully select dependencies and use useCallback and useMemo to prevent unnecessary effects.
Improper cleanup of effects:
Uncleared subscriptions or timers can cause memory leaks.
Best practice: Always return a cleanup function from the effect if it subscribes to any external data sources or utilizes resources that require cleanup.
Using useEffect for computations unrelated to side effects:
useEffect is intended for side effects, not for computations that should affect the rendering result.
Best practice: For computations that alter the output of a component, use useState and useMemo.
Using the React hook useEffect is a key element in creating efficient and functional React components. Once you master its usage, try not to overcomplicate the useEffect hook. Remember, it's better to use a separate hook for each effect for clarity and simplicity of code.