React hook之useRef

React useRef 詳解

useRef 是 React 提供的一個 Hook,用于在函數組件中創建可變的引用對象。它在 React 開發中有多種重要用途,下面我將全面詳細地介紹它的特性和用法。

基本概念

1. 創建 ref

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

2. 核心特性

  • 跨渲染周期保存值:ref 對象在組件的整個生命周期內保持不變
  • 修改不會觸發重新渲染:改變 .current 屬性不會導致組件重新渲染
  • 直接訪問 DOM 元素:最常見的用途之一

主要用途

1. 訪問 DOM 元素

最常見的用法是訪問 JSX 渲染的 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></>);
}

2. 存儲可變值

可以存儲任何可變值,類似于類組件中的實例屬性:

function Timer() {const intervalRef = useRef();useEffect(() => {intervalRef.current = setInterval(() => {console.log('Timer tick');}, 1000);return () => clearInterval(intervalRef.current);}, []);// ...
}

3. 保存上一次的值

實現獲取上一次 props 或 state 的功能:

function Counter() {const [count, setCount] = useState(0);const prevCountRef = useRef();useEffect(() => {prevCountRef.current = count;});const prevCount = prevCountRef.current;return (<div><p>Current: {count}, Previous: {prevCount}</p><button onClick={() => setCount(count + 1)}>Increment</button></div>);
}

4. 避免重復執行 useEffect

解決 React 18+ 嚴格模式下 useEffect 執行兩次的問題:

useEffect(() => {const executedRef = useRef(false);if (!executedRef.current) {executedRef.current = true;// 你的初始化代碼}
}, []);

高級用法

1. 轉發 refs (forwardRef)

將 ref 傳遞給子組件:

const FancyInput = React.forwardRef((props, ref) => {return <input ref={ref} className="fancy-input" {...props} />;
});function App() {const inputRef = useRef();useEffect(() => {inputRef.current.focus();}, []);return <FancyInput ref={inputRef} />;
}

2. 回調 refs

動態設置多個 ref:

function MeasureExample() {const [height, setHeight] = useState(0);const measuredRef = useCallback(node => {if (node !== null) {setHeight(node.getBoundingClientRect().height);}}, []);return (<div ref={measuredRef}><h1>Hello, world</h1><p>The above header is {Math.round(height)}px tall</p></div>);
}

3. 與第三方 DOM 庫集成

function Canvas() {const canvasRef = useRef(null);useEffect(() => {const ctx = canvasRef.current.getContext('2d');// 使用第三方庫繪制new ThirdPartyLibrary(ctx);}, []);return <canvas ref={canvasRef} />;
}

useRef 與 useState 的區別

特性useRefuseState
觸發重新渲染
值更新時機同步異步
適合存儲DOM 引用、可變變量、計時器需要觸發 UI 更新的狀態
訪問方式.current 屬性直接訪問狀態變量
初始化參數作為 .current 初始值參數作為初始狀態

注意事項

  1. 不要在渲染期間寫入/讀取 ref.current

    // 錯誤示例
    function MyComponent() {const myRef = useRef();myRef.current = 123; // 不應該在渲染期間修改return <div>{myRef.current}</div>; // 也不應該依賴渲染期間的值
    }
    
  2. ref 不會自動通知內容變化

    • 如果需要在 ref 變化時執行代碼,使用回調 ref 或手動監聽
  3. 多個 refs 合并

    function useCombinedRefs(...refs) {return useCallback(el => {refs.forEach(ref => {if (!ref) return;if (typeof ref === 'function') ref(el);else ref.current = el;});}, refs);
    }
    
  4. 服務端渲染(SSR)注意事項

    • ref 在服務端渲染時不會被序列化
    • 在服務端和客戶端渲染結果要保持一致

性能優化

useRef 本身是輕量級的,但以下情況需要注意:

  1. 避免在渲染函數中創建新 ref

    // 不好 - 每次渲染都創建新 ref
    function Component() {return <Child ref={useRef()} />;
    }// 好 - ref 只創建一次
    function Component() {const ref = useRef();return <Child ref={ref} />;
    }
    
  2. 大量 ref 的內存問題

    • 當需要為列表中的每個元素創建 ref 時,考慮使用 ref 回調函數 或 第三方庫

總結

useRef 是 React Hooks 中一個非常實用的工具,它:

  • 提供了一種訪問 DOM 節點的方式
  • 可以存儲不會觸發重新渲染的可變值
  • 在組件的整個生命周期內保持引用不變
  • 是集成第三方庫和實現高級模式的利器

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

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

相關文章

開疆智能ModbusTCP轉Canopen網關連接AB PLC與臺達伺服通訊案例

本案例是羅克韋爾PLC通過開疆智能ModbusTCP轉Canopen網關連接臺達A2伺服的配置案例。 配置方法&#xff1a; 首先打開PLC配置軟件“Studio5000”并新建項目導入通訊文件 對功能塊進行設置 填寫本地IP地址以及服務區IP地址以及寄存器 填寫寄存器地址數量及使能 確認無誤后將配置…

用 LoRA 對 Qwen2.5-VL 模型進行SFT - LoRA微調流程

用 LoRA 對 Qwen2.5-VL 模型進行SFT - LoRA微調流程 flyfish ┌──────────────────────────────────────────────────────────────────────────┐ │ 環境準備與啟動 …

熵最小化Entropy Minimization (二): 案例實施

前面介紹了熵最小化、常用的權重函數匯總、半監督學習&#xff1a;低密度分離假設 (Low-Density Separation Assumption)、標簽平滑、信息最大化等相關的知識點&#xff0c;本文采用一個MNIST10分類的數據集來進一步體會它們的效果。 案例實施 對比方法 純監督學習方法&…

聯邦學習聚合參數操作詳解

聯邦學習中常見的模型聚合操作&#xff0c;具體用于對來自多個客戶端的模型更新進行聚合&#xff0c;以得到全局模型。在聯邦學習框架下&#xff0c;多個客戶端在本地訓練各自的模型后&#xff0c;會將模型更新&#xff08;通常是模型的權重&#xff09;發送到中央服務器&#…

藍牙 BLE 掃描面試題大全(2):進階面試題與實戰演練

前文覆蓋了 BLE 掃描的基礎概念與經典問題藍牙 BLE 掃描面試題大全(1)&#xff1a;從基礎到實戰的深度解析-CSDN博客&#xff0c;但實際面試中&#xff0c;企業更關注候選人對復雜場景的應對能力&#xff08;如多設備并發掃描、低功耗與高發現率的平衡&#xff09;和前沿技術的…

基于Flask實現的醫療保險欺詐識別監測模型

基于Flask實現的醫療保險欺詐識別監測模型 項目截圖 項目簡介 社會醫療保險是國家通過立法形式強制實施&#xff0c;由雇主和個人按一定比例繳納保險費&#xff0c;建立社會醫療保險基金&#xff0c;支付雇員醫療費用的一種醫療保險制度&#xff0c; 它是促進社會文明和進步的…

機房斷電后 etcd 啟動失敗的排查與快速恢復實錄

目錄 機房斷電后 etcd 啟動失敗的排查與快速恢復實錄 背景與問題起因 報錯分析 解決方案&#xff1a;刪除 member 數據重新初始化 步驟 1&#xff1a;停止 etcd 容器或服務 步驟 2&#xff1a;刪除 member 目錄 步驟 3&#xff1a;重啟 etcd 服務 附加提醒 總結與后續…

Linux上并行打包壓縮工具

文章目錄 Linux上并行打包壓縮工具1. **Pigz (Parallel gzip)**2. **Pbzip2 (Parallel bzip2)**3. **Pixz (Parallel xz)**4. **Zstd (支持多線程)**5. **GNU Parallel 傳統工具**6. **Fastest Tools (綜合建議)**注意事項&#xff1a; tar和zstd多線程壓縮和解壓**1. 多線程壓…

【K8S系列】K8S中Service 無法訪問問題的深度分析

摘要 &#xff1a; 本文是關于 Kubernetes 中 Service 無法訪問問題的深度分析&#xff0c;結合根本原因、診斷策略與解決方案的系統性指南&#xff1a; Kubernetes Service 訪問故障全景解析&#xff1a;從底層機制到實戰修復 Service 作為 Kubernetes 集群內網絡通信的核心抽…

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解題思路2. 代碼實現 題目鏈接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解題思路 這一題其實就是一個腦筋急轉彎&#xff0c;要想要能夠將所有的電腦解鎖&#x…

進行性核上性麻痹護理指南:全維度守護健康

進行性核上性麻痹是一種罕見的神經系統退行性疾病&#xff0c;會導致患者出現運動障礙、吞咽困難、認知障礙等癥狀。科學的健康護理對延緩病情發展、提升患者生活質量至關重要。 飲食護理&#xff1a;由于患者常存在吞咽困難&#xff0c;食物應選擇糊狀、軟爛的類型&#xff0c…

【淺析賽題,國賽一等獎水平:思路+模型:】2025 年第八屆河北省研究生數學建模競賽:A 題 基于圖論的復雜網絡分析與可視化建模

問題一&#xff1a;社交網絡拓撲結構分析與影響力評估 基礎模型 有向加權圖構建&#xff1a;將用戶設為節點&#xff0c;互動關系為有向邊&#xff0c;以互動頻率&#xff08;如一定時間內點贊、評論、轉發次數&#xff09;或加權求和&#xff08;賦予不同互動類型不同權重&a…

web3-去中心化金融深度剖析:DEX、AMM及兌換交易傳播如何改變世界

web3-去中心化金融深度剖析&#xff1a;DEX、AMM及兌換交易傳播如何改變世界 金融問題 1.個人投資&#xff1a;在不同的時間和可能的情況&#xff08;狀態&#xff09;下積累財富 2.商業投資&#xff1a;為企業家和企業提供投資生產性活動的資源 目標&#xff1a;跨越時間和…

【筆記】NVIDIA AI Workbench 安裝記錄

前言 NVIDIA AI Workbench 簡介 NVIDIA AI Workbench 是一款由 NVIDIA 推出的集成化開發工具&#xff0c;旨在簡化人工智能和機器學習的開發流程。它提供從數據準備到模型訓練、優化及部署的全套工具鏈&#xff0c;支持跨平臺協作&#xff0c;適合開發者、數據科學家和企業團隊…

積累-Vue.js 開發實用指南:ElementUI 與核心技巧

一、ElementUI 組件高效使用 1. Table 組件展開行優化實現 場景需求&#xff1a;僅在展開行時動態加載數據&#xff0c;避免不必要的接口調用 實現方案&#xff1a; // expand行展開的時候調用expandOpen: async (row, expandedRows) > {// 實時更新展開列const index e…

【BUG】記STM32F030多通道ADC DMA讀取亂序問題

STM32F0多通道ADC的校準順序與DMA亂序問題的本質 聲明&#xff1a;本段轉載&#xff1a;https://www.cnblogs.com/chihirosan/p/5458673.html 問題描述 通過 uint16_t ConvData[8]保存DMA搬運的ADC轉換數值&#xff0c;但是這個數組數值的順序總是和ADC不是順序對應的。比如用7…

Java - Mysql數據類型對應

Mysql數據類型java數據類型備注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮點型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定長度字符串VARCHARjava.lang…

今天刷SQL

多說幾句&#xff0c;JAVA真不行了&#xff1f; 剛剛看到那個tiobe最新的指數&#xff0c;JAVA只剩下8.84%&#xff1f;感覺上次看的時候還有百分之十呢。 185-department-top-three-salaries https://leetcode.com/problems/department-top-three-salaries/description/ 公…

【SQL學習筆記1】增刪改查+多表連接全解析(內附SQL免費在線練習工具)

可以使用Sqliteviz這個網站免費編寫sql語句&#xff0c;它能夠讓用戶直接在瀏覽器內練習SQL的語法&#xff0c;不需要安裝任何軟件。 鏈接如下&#xff1a; sqliteviz 注意&#xff1a; 在轉寫SQL語法時&#xff0c;關鍵字之間有一個特定的順序&#xff0c;這個順序會影響到…

【計算機網絡】SDN

SDN這種新型網絡體系結構的核心思想&#xff1a;把網絡的控制層面與數據層面分離&#xff0c;而讓控制層面利用軟件來控制數據層面中的許多設備。 OpenFlow協議可以被看成是SDN體系結構中控制層面與數據層面之間的通信接口。 在SDN中取代傳統路由器中轉發表的是“流表”&…