React useEffect Hook
The useEffect
hook is an essential part of React's Hooks API that allows you to perform side effects in function components. Side effects are operations that can affect other components, cannot be done during rendering, and include things like data fetching, subscriptions, manually changing the DOM, and timers. The useEffect
hook unifies the use of side effects in function components and serves as a replacement for lifecycle methods in class components such as componentDidMount
, componentDidUpdate
, and componentWillUnmount
. useEffect 是一個 React Hook 函數,用於在 React 組件中創建不是由事件引起而是由渲染本身引起的操作,比如發送 AJAX 請求,更改 DOM 等等。
需求: 在組件渲染完畢之後,立刻從 server 端獲取 API 數據並顯示到頁面中。
Basic Usage
The basic syntax of useEffect
is as follows:
useEffect(() => {
// Side effect logic here
}, [dependency]);
參數 1 是一個函數, 可以把它叫作副作用函數,在函數內部可以放置要執行的操作。
參數 2 是一個數組(可選參), 在數組裡放置依賴項,不同依賴項會影響第一個函數參數的執行,當一個空數組的時候,副作用函數只會在組件渲染在完畢之後執行一次。
The first argument is a function where you place the side effect logic. This function can optionally return another function that cleans up the side effect, similar to
componentWillUnmount
in class components.The second argument is an optional array of dependencies. React will only re-run the side effect if one of the dependencies has changed since the last render. If the dependency array is:
- Omitted: The side effect runs after every rendering.
- Empty (
[]
): The side effect runs once after the initial render, similar tocomponentDidMount
. - Contains values: The side effect runs only when any dependency value changes.
Examples
Fetching Data
useEffect(() => {
const fetchData = async () => {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
};
fetchData();
}, []); // Runs only on the first render
Subscriptions or Event Listeners
useEffect(() => {
const handleResize = () => {
console.log(window.innerWidth);
};
window.addEventListener('resize', handleResize);
// Cleanup function
return () => {
window.removeEventListener('resize', handleResize);
};
}, []); // Runs only on the first render and when the component unmounts
Updating the Document Title
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // Runs on the first render and every time 'count' changes
Cleaning Up
Some effects require cleanup to prevent memory leaks, such as removing event listeners or canceling network requests. To do this, the function passed to useEffect
may return a cleanup function:
useEffect(() => {
const timerID = setInterval(() => {
console.log('Tick');
}, 1000);
return () => {
clearInterval(timerID);
};
}, []); // Runs only on the first render and when the component unmounts
Rules of Hooks
When using useEffect
, you should follow the rules of Hooks:
- Only call Hooks at the top level of your React function. Don’t call Hooks inside loops, conditions, or nested functions.
- Only call Hooks from React function components or custom Hooks.
Conclusion
The useEffect
hook is a powerful feature in React that replaces lifecycle methods for side effects in functional components. It provides a declarative approach to running side effects, making it easier to manage side effects in your React applications.
Dependency Type | Timing of Effect Function Execution |
---|---|
No dependencies | Executes on initial render + when component updates |
Empty array | Executes only on initial render |
Specific dependencies | Executes on initial render + when specific dependencies change |
In React, the useEffect
hook allows you to perform side effects in your components. Some side effects might require cleanup to prevent memory leaks, such as subscriptions, timers, event listeners, or any manual changes to the DOM that need to be undone when the component unmounts or before the component re-renders with updated effects.
To perform cleanup, the function passed to useEffect
may return a cleanup function. React will run the cleanup function when the component unmounts, as well as before re-running the effect due to changes in its dependencies.
Here's an example demonstrating how to clean up an event listener with useEffect
:
import React, { useEffect } from 'react';
function Example() {
useEffect(() => {
// Set up
const handleResize = () => {
console.log('Window resized');
};
// Subscribe to window resize event
window.addEventListener('resize', handleResize);
// Clean up
return () => {
window.removeEventListener('resize', handleResize);
};
}, []); // Empty dependency array means this effect runs only on mount and unmount
return <div>Check the console when resizing the window.</div>;
}
In this example:
- When the component mounts, it subscribes to the window resize event.
- The cleanup function (returned from the effect) removes the event listener. This cleanup prevents potential memory leaks and ensures that if the component is removed, it won't try to modify the state or perform any action when the event fires.
- Because the dependency array is empty (
[]
), the effect runs only once after the initial render, and the cleanup function runs only when the component unmounts.
This pattern is crucial for avoiding side effects from running when they're not supposed to, keeping your components performant and bug-free. Remember that every effect may return a cleanup function, so you can use this pattern whenever your effect subscribes to external data sources, adds event listeners, sets timers, or needs to perform any manual cleanup.