深入解析 React 的 useEffect:從入門到實戰

文章目錄

  • 前言
    • 一、為什么需要 `useEffect`?
      • 核心作用:
    • 二、`useEffect` 的基礎用法
      • 1. 基本語法
      • 2. 依賴項數組的作用
    • 三、依賴項數組演示
      • 1. 空數組 `[]`:
      • 2.無依賴項(空)
      • 3.有依賴項
    • 四、清理副作用函數
      • 實戰案例演示
      • 1. 清除定時器
      • 2. 取消網絡請求
  • 總結


前言

在 React 函數組件中,useEffect 是處理副作用(Side Effects)的核心 Hook。無論是數據獲取、訂閱事件、手動操作 DOM,還是其他異步任務,useEffect 都能幫助開發者優雅地管理這些副作用。然而,它的使用場景復雜且容易踩坑。本文將帶你從基礎到實戰,全面掌握 useEffect 的核心原理和最佳實踐。


一、為什么需要 useEffect

在類組件中,副作用通常通過生命周期方法(如 componentDidMountcomponentDidUpdatecomponentWillUnmount)管理。但在函數組件中,由于沒有生命周期方法,React 提供了 useEffect 來統一處理這些場景。

核心作用:

  1. 數據獲取:在組件掛載后從 API 獲取數據。
  2. 訂閱/取消訂閱:如 WebSocket、事件監聽等。
  3. 手動操作 DOM:如調整滾動位置、聚焦輸入框。
  4. 清理副作用:避免內存泄漏或重復操作。

二、useEffect 的基礎用法

1. 基本語法

	import { useEffect } from 'react';function MyComponent() {useEffect(() => {// 副作用代碼return () => {// 清理函數(可選)};}, [dependencies]); // 依賴項數組(可選) return <div>...</div>;}

2. 依賴項數組的作用

  • 空數組:只在組件掛載時執行一次(類似 componentDidMount)。
  • 無依賴項:每次組件渲染后都會執行(類似 componentDidUpdate,但容易引發性能問題)。
  • 有依賴項:當依賴項變化時重新執行。

三、依賴項數組演示

1. 空數組 []

只在組件掛載時執行一次(類似 componentDidMount)**

場景:組件掛載時執行一次初始化操作(如獲取初始數據、訂閱事件)。

	import { useState, useEffect } from 'react';function InitialDataLoader() {const [data, setData] = useState(null);useEffect(() => {async function fetchInitialData() {const response = await fetch('/api/initial-data');const result = await response.json();setData(result);}fetchInitialData();}, []); // 空數組:僅在組件掛載時執行if (!data) return <div>Loading initial data...</div>;return <div>{JSON.stringify(data)}</div>;}
  • useEffect 僅在組件掛載時執行一次,適合初始化操作。
  • 清理函數(可選)通常用于取消訂閱或清除資源(如 AbortController)。

2.無依賴項(空)

無依賴項:每次組件渲染后都會執行(類似 componentDidUpdate,但容易引發性能問題

場景:每次組件渲染后都執行某些操作(如記錄日志、強制更新)。
注意:無依賴項的 useEffect 通常不推薦使用,除非明確需要每次渲染后執行。

	import { useEffect } from 'react';function LoggerComponent() {useEffect(() => {console.log('Component rendered or updated');}); // 無依賴項:每次渲染后都會執行return <div>Check the console for render logs.</div>;}
  • 每次組件渲染(包括狀態更新、父組件更新等)后都會觸發 useEffect
  • 慎用:可能導致性能問題(如無限循環、頻繁 API 調用)。

3.有依賴項

:當依賴項變化時重新執行

場景:依賴項(如狀態、props)變化時重新執行副作用(如數據更新、重新訂閱)。

	import { useState, useEffect } from 'react';function UserData({ userId }) {const [user, setUser] = useState(null);useEffect(() => {async function fetchUser() {const response = await fetch(`/api/users/${userId}`);const data = await response.json();setUser(data);}fetchUser();}, [userId]); // 依賴項:userId 變化時重新執行 if (!user) return <div>Loading user data...</div>;return <div>{user.name}</div>;}// 父組件使用示例function App() {const [currentUserId, setCurrentUserId] = useState(1);return (<div><button onClick={() => setCurrentUserId(2)}>Load User 2</button><UserData userId={currentUserId} /></div>);}
  • userId 變化時(如點擊按鈕切換用戶),useEffect 會重新執行,獲取新用戶數據。
  • 依賴項可以是狀態、props 或其他變量,確保副作用與組件狀態同步。

四、清理副作用函數

在 React 的 useEffect 中,清理副作用函數(cleanup function)用于在組件卸載或依賴項變化時清除之前的副作用(如取消訂閱事件、清除定時器、關閉網絡請求等)。以下是幾個常見的清理副作用函數的示例:

import { useState, useEffect } from "react";function Child() {useEffect(() => {console.log("child 初始化");return () => {console.log("child 卸載了");};});return <div>child</div>;
}
function App() {const [count, setCount] = useState(0);const [state, setState] = useState(true);useEffect(() => {return () => {console.log("我執行了!!!");};}, [count]);return (<><div><button onClick={() => setCount(count + 1)}>+1</button><button onClick={() => setState(!state)}>顯示/隱藏</button></div>{state && <Child />}</>);
}export default App;

在這里插入圖片描述

實戰案例演示

1. 清除定時器

場景:組件中使用了定時器,需要在組件卸載或依賴項變化時清除定時器。

	import { useState, useEffect } from 'react';function TimerComponent() {const [count, setCount] = useState(0);useEffect(() => {const timer = setInterval(() => {setCount((prev) => prev + 1);}, 1000);// 清理函數:清除定時器return () => {clearInterval(timer);};}, []); // 空數組:僅在組件掛載時設置定時;return <div>Count: {count}</div>;}
  • 組件卸載時,clearInterval(timer) 會被調用,避免內存泄漏。

2. 取消網絡請求

場景:組件中發起了網絡請求,需要在組件卸載或依賴項變化時取消請求。

	import { useState, useEffect } from 'react';function DataFetcher({ userId }) {const [data, setData] = useState(null);useEffect(() => {const abortController = new AbortController();async function fetchData() {try {const response = await fetch(`/api/users/${userId}`, {signal: abortController.signal,});const result = await response.json();setData(result);} catch (error) {if (error.name !== 'AbortError') {console.error('Fetch error:', error);}}}fetchData();// 清理函數:取消請求return () => {abortController.abort();};}, [userId]); // 依賴項:userId 變化時重新執行if (!data) return <div>Loading...</div>;return <div>{JSON.stringify(data)}</div>;}

總結

useEffect 是 React 函數組件中管理副作用的強大工具,但需要開發者深入理解其工作原理和潛在問題。通過合理使用依賴項、清理函數和函數式更新,可以避免常見的陷阱,寫出高效、穩定的代碼。

希望本文能幫助你更好地掌握 useEffect,并在實際項目中靈活運用!如果有任何疑問或補充,歡迎在評論區留言討論。 🚀

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/905945.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/905945.shtml
英文地址,請注明出處:http://en.pswp.cn/news/905945.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Ubuntu 更改 Nginx 版本

將 1.25 降為 1.18 先卸載干凈 # 1. 完全卸載當前Nginx sudo apt purge nginx nginx-common nginx-core# 2. 清理殘留配置 sudo apt autoremove sudo rm -rf /etc/apt/sources.list.d/nginx*.list修改倉庫地址 # 添加倉庫&#xff08;通用穩定版倉庫&#xff09; codename$(…

如何在 Windows 10 或 11 中安裝 PowerShellGet 模塊?

PowerShell 是微軟在其 Windows 操作系統上提供的強大腳本語言,可用于通過命令行界面自動化各種任務,適用于 Windows 桌面或服務器環境。而 PowerShellGet 是 PowerShell 中的一個模塊,提供了用于從各種來源發現、安裝、更新和發布模塊的 cmdlet。 本文將介紹如何在 PowerS…

NBA足球賽事直播源碼體育直播M33模板賽事源碼

源碼名稱&#xff1a;體育直播賽事扁平自適應M33直播模板源碼 開發環境&#xff1a;帝國cms7.5 空間支持&#xff1a;phpmysql 帶軟件采集&#xff0c;可以掛著自動采集發布&#xff0c;無需人工操作&#xff01; 演示地址&#xff1a;NBA足球賽事直播源碼體育直播M33模板賽事…

【Python】魔法方法是真的魔法! (第二期)

還不清楚魔術方法&#xff1f; 可以看看本系列開篇&#xff1a;【Python】小子&#xff01;是魔術方法&#xff01;-CSDN博客 【Python】魔法方法是真的魔法&#xff01; &#xff08;第一期&#xff09;-CSDN博客 在 Python 中&#xff0c;如何自定義數據結構的比較邏輯&…

Qt 強大的窗口停靠浮動

1、左邊&#xff1a; 示例代碼&#xff1a; CDockManager::setConfigFlags(CDockManager::DefaultOpaqueConfig); CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true); dockManager new CDockManager(this); // Disabling the Internal Style S…

Linux進程異常退出排查指南

在 Linux 中&#xff0c;如果進程無法正常終止&#xff08;如 kill 命令無效&#xff09;或異常退出&#xff0c;可以按照以下步驟排查和解決&#xff1a; 1. 常規終止進程 嘗試普通終止&#xff08;SIGTERM&#xff09; kill PID # 發送 SIGTERM 信號&#xff08;…

使用tensorRT10部署低光照補償模型

1.低光照補償模型的簡單介紹 作者介紹一種Zero-Reference Deep Curve Estimation (Zero-DCE)的方法用于在沒有參考圖像的情況下增強低光照圖像的效果。 具體來說&#xff0c;它將低光照圖像增強問題轉化為通過深度網絡進行圖像特定曲線估計的任務。訓練了一個輕量級的深度網絡…

SLAM定位常用地圖對比示例

序號 地圖類型 概述 1 格柵地圖 將現實環境柵格化,每一個柵格用 0 和 1 分別表示空閑和占據狀態,初始化為未知狀態 0.5 2 特征地圖 以點、線、面等幾何特征來描繪周圍環境,將采集的信息進行篩選和提取得到關鍵幾何特征 3 拓撲地圖 將重要部分抽象為地圖,使用簡單的圖形表示…

【圖像生成1】Latent Diffusion Models 論文學習筆記

一、背景 本文主要記錄一下使用 LDMs 之前&#xff0c;學習 LDMs 的過程。 二、論文解讀 Paper&#xff1a;[2112.10752] High-Resolution Image Synthesis with Latent Diffusion Models 1. 總體描述 LDMs 將傳統 DMs 在高維圖像像素空間&#xff08;Pixel Space&#x…

通信安全堡壘:profinet轉ethernet ip主網關提升冶煉安全與連接

作為鋼鐵冶煉生產線的安全檢查員&#xff0c;我在此提交關于使用profinet轉ethernetip網關前后對生產線連接及安全影響的檢查報告。 使用profinet轉ethernetip網關前的情況&#xff1a; 在未使用profinet轉ethernetip網關之前&#xff0c;我們的EtherNet/IP測溫儀和流量計與PR…

TIFS2024 | CRFA | 基于關鍵區域特征攻擊提升對抗樣本遷移性

Improving Transferability of Adversarial Samples via Critical Region-Oriented Feature-Level Attack 摘要-Abstract引言-Introduction相關工作-Related Work提出的方法-Proposed Method問題分析-Problem Analysis擾動注意力感知加權-Perturbation Attention-Aware Weighti…

day 20 奇異值SVD分解

一、什么是奇異值 二、核心思想&#xff1a; 三、奇異值的主要應用 1、降維&#xff1a; 2、數據壓縮&#xff1a; 原理&#xff1a;圖像可以表示為一個矩陣&#xff0c;矩陣的元素對應圖像的像素值。對這個圖像矩陣進行 SVD 分解后&#xff0c;小的奇異值對圖像的主要結構貢…

符合Python風格的對象(對象表示形式)

對象表示形式 每門面向對象的語言至少都有一種獲取對象的字符串表示形式的標準方 式。Python 提供了兩種方式。 repr()   以便于開發者理解的方式返回對象的字符串表示形式。str()   以便于用戶理解的方式返回對象的字符串表示形式。 正如你所知&#xff0c;我們要實現_…

springboot配置tomcat端口的方法

在Spring Boot中配置Tomcat端口可通過以下方法實現&#xff1a; 配置文件方式 properties格式 在application.properties中添加&#xff1a;server.port8081YAML格式 在application.yml中添加&#xff1a;server:port: 8082多環境配置 創建不同環境的配置文件&#xff08;如app…

DeepSeek指令微調與強化學習對齊:從SFT到RLHF

后訓練微調的重要性 預訓練使大模型獲得豐富的語言和知識表達能力,但其輸出往往與用戶意圖和安全性需求不完全匹配。業內普遍采用三階段訓練流程:預訓練 → 監督微調(SFT)→ 人類偏好對齊(RLHF)。預訓練階段模型在大規模語料上學習語言規律;監督微調利用人工標注的數據…

Maven 插件擴展點與自定義生命周期

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家&#xff0c;歷代文學網&#xff08;PC端可以訪問&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移動端可微信小程序搜索“歷代文學”&#xff09;總架構師&#xff0c;15年工作經驗&#xff0c;精通Java編…

ecmascript 第6版特性 ECMA-262 ES6

https://blog.csdn.net/zlpzlpzyd/article/details/146125018 在之前寫的文章基礎上&#xff0c;ES6在export和import的基礎外&#xff0c;還有如下特性 特性說明let/const塊級作用域變量聲明>箭頭函數Promise異步編程

CT重建筆記(五)—2D平行束投影公式

寫的又回去了&#xff0c;因為我發現我理解不夠透徹&#xff0c;反正想到啥寫啥&#xff0c;盡量保證內容質量好簡潔易懂 2D平行束投影公式 p ( s , θ ) ∫ ∫ f ( x , y ) δ ( x c o s θ y s i n θ ? s ) d x d y p(s,\theta)\int \int f(x,y)\delta(x cos\theta ysi…

記一次緩存填坑省市區級聯獲取的操作

先說緩存是什么&#xff1f; 緩存主要是解決高并發&#xff0c;大數據場景下&#xff0c;熱點數據快速訪問。緩存的原則首先保證數據的準確和最終數據一致&#xff0c;其次是距離用戶越近越好&#xff0c;同步越及時越好。 再說我們遇到的場景&#xff1a; 接手項目后&#…

無法加載文件 E:\Program Files\nodejs\npm.ps1,因為在此系統上禁止運行腳本

遇到“無法加載文件 E:\Program Files\nodejs\npm.ps1,因為在此系統上禁止運行腳本”這類錯誤&#xff0c;通常是因為你的 PowerShell 執行策略設置為不允許運行腳本。在 Windows 系統中&#xff0c;默認情況下&#xff0c;出于安全考慮&#xff0c;PowerShell 可能會阻止運行未…