Unveiling the Power of useEffect React Hook
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:
- component rendering: Equivalent to componentDidMount in class components. Used to trigger effects (such as API requests) after the component has first rendered to the DOM.
- component update: Equivalent to componentDidUpdate in class components. useEffect can monitor changes to certain values (states or props) and trigger effects when they change.
- removing a component from the DOM: Equivalent to componentWillUnmount in class-based components. The useEffect React hook has the capability to provide a cleanup function that executes when the component is unmounted. This functionality proves helpful for tasks such as unsubscribing from events or clearing timers.
How to use Effects
useEffect takes two arguments:
- Callback Function: This is the main function that will be executed after the component is rendered. This function can perform any side effects required by the component.
- Dependencies Array: An optional array that contains the values that your effect depends on.
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:
Advanced use of the useEffect
Clean up the effect
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!
Async-Await Operations in useEffect
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.
Custom Hooks
Create your own hooks using useEffect to reuse complex effect logic across different components.
Then you can use it from any component like this:
Common Mistakes and Best Practices
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.
Conclusion
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.
like this