Skip to content

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:

jsx
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 to componentDidMount.
    • Contains values: The side effect runs only when any dependency value changes.

Examples

Fetching Data

jsx
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

jsx
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

jsx
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:

jsx
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 TypeTiming of Effect Function Execution
No dependenciesExecutes on initial render + when component updates
Empty arrayExecutes only on initial render
Specific dependenciesExecutes 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:

jsx
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.

Contributors

No contributors

Changelog

No recent changes