詳細解讀react框架中的hooks

React Hooks 是 React 16.8 引入的一項革命性特性,它允許你在函數組件中使用狀態(state)和其他 React 特性,而無需編寫 class 組件。下面將詳細解讀 React Hooks 的核心概念、常用 Hooks 及其工作原理。

一、Hooks 的核心概念

1. 什么是 Hooks

Hooks 是特殊的函數,以"use"開頭(如?useState,?useEffect),讓你能夠"鉤入" React 的狀態和生命周期特性。

2. Hooks 的基本規則

  • 只在最頂層調用 Hooks:不要在循環、條件或嵌套函數中調用 Hook

  • 只在 React 函數組件或自定義 Hook 中調用 Hooks

二、常用內置 Hooks 詳解

1. useState

const [state, setState] = useState(initialState);
  • 用于在函數組件中添加局部狀態

  • 返回一個狀態值和一個更新該狀態的函數

  • 參數可以是初始值或返回初始值的函數(惰性初始化)

示例

function Counter() {const [count, setCount] = useState(0);return (<button onClick={() => setCount(count + 1)}>Clicked {count} times</button>);
}

2. useEffect

useEffect(() => {// 副作用邏輯return () => {// 清理函數(可選)};
}, [dependencies]);
  • 用于處理副作用(數據獲取、訂閱、手動修改 DOM 等)

  • 相當于 class 組件中的?componentDidMount,?componentDidUpdate?和?componentWillUnmount?的組合

  • 第二個參數是依賴數組,控制 effect 的執行時機

示例

function Example() {const [count, setCount] = useState(0);useEffect(() => {document.title = `You clicked ${count} times`;return () => {// 清理工作};}, [count]); // 僅在 count 更改時更新
}

3. useContext

const value = useContext(MyContext);
  • 用于訂閱 React 的 Context 對象

  • 接收一個 context 對象(React.createContext 的返回值)并返回該 context 的當前值

示例

const ThemeContext = React.createContext('light');function ThemedButton() {const theme = useContext(ThemeContext);return <button className={theme}>I am styled by theme context!</button>;
}

4. useReducer

const [state, dispatch] = useReducer(reducer, initialArg, init);
  • useState 的替代方案,適合復雜 state 邏輯

  • 接收一個形如?(state, action) => newState?的 reducer 函數

  • 返回當前 state 和配套的 dispatch 方法

示例

function counterReducer(state, action) {switch (action.type) {case 'increment':return {count: state.count + 1};case 'decrement':return {count: state.count - 1};default:throw new Error();}
}function Counter() {const [state, dispatch] = useReducer(counterReducer, {count: 0});return (<>Count: {state.count}<button onClick={() => dispatch({type: 'increment'})}>+</button><button onClick={() => dispatch({type: 'decrement'})}>-</button></>);
}

5. useCallback

const memoizedCallback = useCallback(() => {doSomething(a, b);
}, [a, b]);
  • 返回一個 memoized 回調函數

  • 僅在依賴項改變時才會更新

  • 用于優化子組件渲染,避免不必要的重新渲染

6. useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  • 返回一個 memoized 值

  • 僅在依賴項改變時才會重新計算

  • 用于性能優化,避免每次渲染都進行高開銷計算

7. useRef

const refContainer = useRef(initialValue);
  • 返回一個可變的 ref 對象,其?.current?屬性被初始化為傳入的參數

  • 常用于訪問 DOM 節點或存儲可變值而不引起重新渲染

示例

function TextInputWithFocusButton() {const inputEl = useRef(null);const onButtonClick = () => {inputEl.current.focus();};return (<><input ref={inputEl} type="text" /><button onClick={onButtonClick}>Focus the input</button></>);
}

三、Hooks 的工作原理

1. Hooks 的調用順序

React 依賴于 Hooks 的調用順序來正確關聯狀態和對應的 Hook。這就是為什么不能在條件或循環中調用 Hook。

2. Hooks 的實現機制

  • 每個組件有一個"記憶單元格"列表(可以看作是一個數組)

  • 每次調用 Hook 時,它都會讀取當前的單元格(或初始化它),然后將指針移動到下一個

  • 這就是為什么 Hook 的調用順序必須一致

3. 自定義 Hook

可以創建自己的 Hook 來復用狀態邏輯。自定義 Hook 是一個名稱以"use"開頭的 JavaScript 函數,它可以調用其他 Hook。

示例

function useFriendStatus(friendID) {const [isOnline, setIsOnline] = useState(null);useEffect(() => {function handleStatusChange(status) {setIsOnline(status.isOnline);}ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);return () => {ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);};}, [friendID]);return isOnline;
}

四、Hooks 的優勢

  1. 簡化組件邏輯:解決了 class 組件中生命周期函數經常包含不相關的邏輯的問題

  2. 復用狀態邏輯:通過自定義 Hook 可以輕松復用狀態邏輯,無需高階組件或 render props

  3. 更直觀的代碼:Hooks 讓你根據代碼的用途而非生命周期方法來組織代碼

  4. 更小的打包體積:函數組件通常比 class 組件更輕量

五、Hooks 的最佳實踐

  1. 按功能而非生命周期組織代碼:將相關的邏輯放在同一個 useEffect 中

  2. 合理使用依賴數組:確保 useEffect 和 useCallback/useMemo 的依賴項完整且準確

  3. 避免過度優化:不要過早使用 useMemo 和 useCallback,先測量再優化

  4. 自定義 Hook 命名以"use"開頭:這是 React 識別 Hook 的方式

  5. 考慮使用 eslint-plugin-react-hooks:幫助檢測 Hook 規則的違反

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

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

相關文章

主機IP動態變化時如何通過固定host.docker.internal訪問本機服務

場景需求——主機IP動態變化時&#xff0c;通過固定的 http://host.docker.internal:11555 訪問本機服務&#xff0c;核心問題在于 host.docker.internal 的解析邏輯與動態IP的適配。以下是分步解決方案&#xff1a; 一、核心原理&#xff1a;host.docker.internal 的本質與局…

插值算法 - 最近鄰插值實現

目錄 1. 導入必要的庫 2. nearest_neighbor_interpolation 3. 測試代碼 數學原理 完整代碼 本文實現了基于最近鄰插值算法的圖像縮放功能。 它使用 Python 編寫,主要依賴于NumPy和PIL(Python Imaging Library)庫。 NumPy用于高效的數值計算,而PIL僅用于圖像的加載和…

windows中搭建Ubuntu子系統

windows中搭建虛擬環境 1.配置2.windows中搭建Ubuntu子系統2.1windows配置2.1.1 確認啟用私有化2.1.2 將wsl2設置為默認版本2.1.3 確認開啟相關配置2.1.4重啟windows以加載更改配置 2.2 搭建Ubuntu子系統2.2.1 下載Ubuntu2.2.2 遷移位置 3.Ubuntu子系統搭建docker環境3.1安裝do…

MySQL事務機制

目錄 原子性 持久性 隔離性 隔離級別(并發事務之間的關系) 讀未提交 讀已提交 可重復讀 串行化(最嚴格的隔離級別) 一致性 問題 不可重復讀性(已經提交的數據) 什么是臟讀問題(未提交的數據)? 幻讀 保存點 自動提交機制--autocommit 會話隔離級別與全局隔離級…

Cadence學習筆記之---直插元件的封裝制作

目錄 01 | 引 言 02 | 環境描述 03 | 操作步驟 04 | 結 語 01 | 引 言 在之前發布的Cadence小記中&#xff0c;已經講述了怎樣制作熱風焊盤&#xff0c;貼片(SMD)焊盤、通孔、過孔&#xff0c;以及貼片元件的封裝。 本篇關于Cadence的小記主要講如何制作直插元件的封裝。 …

【第四十周】文獻閱讀:用于檢索-增強大語言模型的查詢與重寫

目錄 摘要Abstract用于檢索-增強大語言模型的查詢與重寫研究背景方法論基于凍結LLM的重寫方案基于可訓練重寫器的方案重寫器預熱訓練&#xff08;Rewriter Warm-up&#xff09;強化學習&#xff08;Reinforcement Learning&#xff09; 創新性實驗結果局限性總結 摘要 這篇論文…

java學習總結(if switch for)

一.基本結構 1.單分支if int num 10; if (num > 5) {System.out.println("num 大于 5"); } 2.雙分支if-else int score 60; if (score > 60) {System.out.println("及格"); } else {System.out.println("不及格"); } 3.多分支 int…

yum的基本操作和vim指令

在我們的手機端或者Windows上下載軟件&#xff0c;可以在相應的應用商店或者官網進行下載&#xff0c;這樣對于用戶來說十分的方便和便捷。而在Linux上&#xff0c;也有類似的安裝方式&#xff0c;我們來一一了解一下。 Linux安裝軟件的3種方法 源代碼安裝 在Linux下安裝軟件…

C++ CUDA開發入門

CUDA開發筆記 文章目錄 CUDA開發筆記[toc]1 概述2 環境3 命令行編譯4 CMAKE引入CUDA5 vscode開發CUDA6 Qt中使用CUDA-CMake7 QMake配置CUDA8 核函數9 核函數調用9.1 核函數調用語法9.2 執行配置參數詳解9.3 關鍵調用步驟9.4 重要注意事項9.5 調用示例分析9.6 最佳實踐建議 10 線…

llm開發框架新秀

原文鏈接:https://i68.ltd/notes/posts/20250404-llm-framework3/ google開源ADK-Agent Development Kit 開源的、代碼優先的 Python 工具包&#xff0c;用于構建、評估和部署具有靈活性和控制力的復雜智能體項目倉庫:https://github.com/google/adk-python 2.6k項目文檔:Age…

VM——相機拍照失敗

1、問題&#xff1a;相機頻閃觸發&#xff0c;在MVS中正常出圖&#xff0c;在VM中出現拍照失敗 2、解決&#xff1a; 1、首先排查網絡設置&#xff08;巨幀是否設置&#xff09; 2、電腦的所有防火墻是否關閉 3、在MVS中恢復相機的設置參數為默認參數&#xff0c;刪除VM中的全…

【時頻譜分析】小波分析

算法配置頁面&#xff0c;也可以一鍵導出結果數據 報表自定義繪制 獲取和下載【PHM學習軟件PHM源碼】的方式 獲取方式&#xff1a;Docshttps://jcn362s9p4t8.feishu.cn/wiki/A0NXwPxY3ie1cGkOy08cru6vnvc

怎么免費下載GLTF/GLB格式模型文件,還可以在線編輯修改

? 現在非常流行glb格式模型&#xff0c;和gltf格式文件&#xff0c;可是之類模型網站非常非常少 1&#xff0c;咱們先直接打開http://glbxz.com 官方glb下載網站 glbxz.com 2 可以搜索&#xff0c;自己想要的模型關鍵詞 3&#xff0c;到自己想下載素材頁面 4&#xff0c;…

【6】深入學習http模塊(萬字)-Nodejs開發入門

深入學習http模塊 前言http一個Web服務器項目創建代碼運行代碼解析 Server屬性&#xff1a;keepAlive屬性&#xff1a;keepAliveTimeout屬性&#xff1a;maxHeaderSize屬性&#xff1a;requestTimeout屬性&#xff1a;maxRequestsPerSocket方法&#xff1a;close()方法&#xf…

buuctf sql注入類練習

BUU SQL COURSE 1 1 實例無法訪問 / Instance cant be reached at that time | BUUCTF但是這個地方很迷惑就是這個 一個 # 我們不抓包就不知道這個是sql注入類的判斷是 get 類型的sql注入直接使用sqlmap我們放入到1.txt中 目的是 優先檢測 ?id1>python3 sqlmap.py -r 1.t…

(即插即用模塊-特征處理部分) 三十二、(TGRS 2024) MDAF 多尺度雙表示對齊過濾器

文章目錄 1、Multiscale Dual-Representation Alignment Filter2、代碼實現 paper&#xff1a;SFFNet: A Wavelet-Based Spatial and Frequency Domain Fusion Network for Remote Sensing Segmentation Code&#xff1a;https://github.com/yysdck/SFFNet 1、Multiscale Dual-…

Python 中為什么 hash(-1) == hash(-2)?

推薦超級課程: 本地離線DeepSeek AI方案部署實戰教程【完全版】Docker快速入門到精通Kubernetes入門到大師通關課AWS云服務快速入門實戰目錄 讓我們從哪里開始?獲取源代碼!讓我們瀏覽一下這是正確/完整的答案嗎?結論前幾天在瀏覽 Reddit 時,我在 r/Python 上看到了這樣一個…

基于PySide6與pycatia的CATIA繪圖比例智能調節工具開發全解析

引言&#xff1a;工程圖紙自動化處理的技術革新 在機械設計領域&#xff0c;CATIA圖紙的比例調整是高頻且重復性極強的操作。傳統手動調整方式效率低下且易出錯。本文基于PySide6pycatia技術棧&#xff0c;提出一種支持智能比例匹配、實時視圖控制、異常自處理的圖紙批處理方案…

macos下 ragflow二次開發環境搭建

參考官網鏈接 https://ragflow.io/docs/dev/launch_ragflow_from_source虛擬環境 git clone https://github.com/infiniflow/ragflow.git cd ragflow/ # if not pipx, please install it at first pip3 install pipxpipx install uv uv sync --python 3.10 --all-extras 安裝 …

libva之ffavdemo分析

ffavdemo 代碼庫實現了一個基于FFmpeg和VAAPI的硬件加速視頻解碼與渲染框架&#xff0c;主要用于演示視頻解碼與渲染的完整硬件加速流程。支持多種渲染后端&#xff08;X11、DRM、EGL&#xff09;&#xff0c;適應不同顯示環境。包含視頻處理過濾器&#xff0c;可進行格式轉換和…