重新理解?React?useRef原理
為什么要有 useRef?
React.useRef 是 React Hooks 中的一種,它提供了一種可以在函數(shù)組件中存儲可變值的方式。與 useState 不同,useRef 存儲的值不會引起組件的重新渲染。
我們使用 useRef 主要有以下幾個原因:
保存 DOM 元素的引用
在函數(shù)組件中,我們無法像類組件中那樣直接使用 this 來獲取 DOM 元素的引用。而 useRef 可以用來保存 DOM 元素的引用,方便我們獲取或修改其屬性。
保存組件的狀態(tài)
在函數(shù)組件中,每次組件重新渲染時,所有的變量都會被重新聲明和初始化。為了在多次渲染之間保留一些數(shù)據(jù),我們可以使用 useRef 來保存這些數(shù)據(jù),它們在組件的整個生命周期中保持不變。
避免重新渲染的性能問題
在某些情況下,我們需要保存一些數(shù)據(jù),但是這些數(shù)據(jù)并不需要觸發(fā)重新渲染。如果使用 useState,每次更新這些數(shù)據(jù)都會觸發(fā)組件的重新渲染,從而浪費性能。而使用 useRef 可以避免這個問題。
在組件之間傳遞數(shù)據(jù)
在函數(shù)組件中,我們可以使用 useContext 或 useReducer 等鉤子來在組件之間傳遞數(shù)據(jù)。但是有些情況下,我們只需要簡單地在組件之間傳遞一個變量或者一個函數(shù),此時使用 useRef 可以更加方便。
代碼示例
使用 useRef 存儲可變值:
import React, { useRef } from 'react'; function App() { const counterRef = useRef(0); function handleClick() { counterRef.current += 1; console.log(counterRef.current); } return ( <button onClick={handleClick}> Click me </button> ); }
在這個例子中,我們使用 useRef 創(chuàng)建了一個名為 counterRef 的變量,并初始化為 0。每次按鈕被點擊時,我們都會將 counterRef.current 的值加 1,并將結(jié)果打印到控制臺中。
使用 useRef 存儲 DOM 元素的引用:
import React, { useRef } from 'react'; function App() { const inputRef = useRef(null); function handleClick() { inputRef.current.focus(); } return ( <> <input type="text" ref={inputRef} /> <button onClick={handleClick}> Focus input </button> </> ); }
在這個例子中,我們使用 useRef 創(chuàng)建了一個名為 inputRef 的變量,并將其賦值為 null。在組件中,我們將 input 元素的 ref 屬性設置為 inputRef。每次按鈕被點擊時,我們調(diào)用 inputRef.current.focus() 來將輸入框聚焦。
useRef 的特點
- 會返回一個可變的 ref 對象。
- 可以保存任何可變值,類似于在 class 組件中使用實例變量。
- 返回的 ref 對象在組件的整個生命周期中保持不變。
- 并不會在每次組件渲染時都生成新的 ref 對象,因此可以用來保存一些不需要觸發(fā)重新渲染的數(shù)據(jù)。
- 可以用來引用 DOM 元素,用于獲取或修改其屬性。
- 可以用來在函數(shù)組件之間傳遞數(shù)據(jù)。
- 可以模擬實例變量,用于保存函數(shù)組件中的狀態(tài)。
useRef 和 useState 的區(qū)別
useRef 和 useState 有以下幾個區(qū)別:
- useRef 返回的是一個可變的 ref 對象,而 useState 返回的是一個可變的 state 值和一個更新 state 的函數(shù)。
- useRef 主要用于保存一個可變值,并不會觸發(fā)組件重新渲染,而 useState 能夠觸發(fā)組件重新渲染。
- useRef 可以在組件渲染的過程中保持數(shù)據(jù)的穩(wěn)定,而 useState 每次渲染都會重新計算 state 值。
- useRef 可以用于訪問 DOM 元素,而 useState 不能。
使用場景
具體使用場景和每個場景下的代碼示例:
存儲定時器的 ID
定時器是 JavaScript 中常見的一種異步操作。在函數(shù)組件中,我們可以使用 useRef 存儲定時器的 ID,以便在組件卸載時清除定時器。
import React, { useState, useEffect, useRef } from 'react'; function App() { const [count, setCount] = useState(0); const intervalRef = useRef(null); useEffect(() => { intervalRef.current = setInterval(() => { setCount(c => c + 1); }, 1000); return () => clearInterval(intervalRef.current); }, []); return ( <div> <p>{count}</p> <button onClick={() => clearInterval(intervalRef.current)}> Stop timer </button> </div> ); }
在這個例子中,我們使用 useRef 創(chuàng)建了一個名為 intervalRef 的變量,并將其初始化為 null。在 useEffect 中,我們使用 setInterval 創(chuàng)建了一個定時器,并將其 ID 存儲在 intervalRef.current 中。在組件卸載時,我們使用 clearInterval 來清除定時器。點擊 Stop timer 按鈕時,我們也會使用 clearInterval 來停止定時器。
存儲上一次的 props 或 state 值
有時候我們需要在組件更新時和之前的 props 或 state 進行比較。在這種情況下,我們可以使用 useRef 存儲上一次的值。
import React, { useState, useEffect, useRef } from 'react'; function App() { const [count, setCount] = useState(0); const prevCountRef = useRef(null); useEffect(() => { prevCountRef.current = count; }); const prevCount = prevCountRef.current; return ( <div> <p>Current count: {count}</p> {prevCount && ( <p>Previous count: {prevCount}</p> )} <button onClick={() => setCount(c => c + 1)}> Increase count </button> </div> ); }
在這個例子中,我們使用 useRef 創(chuàng)建了一個名為 prevCountRef 的變量,并將其初始化為 null。在 useEffect 中,我們將 count 的值存儲在 prevCountRef.current 中。在組件更新時,我們通過 prevCountRef.current 獲取上一次的 count 值,并將其展示在頁面上。每次 count 更新時,prevCountRef.current 的值也會被更新。
存儲 DOM 元素的引用
在函數(shù)組件中,我們無法直接使用類組件中的 this.refs。因此,我們可以使用 useRef 存儲 DOM 元素的引用,以便進行 DOM 操作。
import React, { useRef } from 'react'; function App() { const inputRef = useRef(null); function handleFocus() { inputRef.current.style.backgroundColor = 'yellow'; } function handleBlur() { inputRef.current.style.backgroundColor = 'white'; } return ( <> <input type="text" ref={inputRef} onFocus={handleFocus} onBlur={handleBlur} /> <button onClick={() => inputRef.current.focus()}> Focus input </button> </> ); }
在這個例子中,我們使用 useRef 創(chuàng)建了一個名為 inputRef 的變量,并將其初始化為 null。在組件中,我們將 input 元素的 ref 屬性設置為 inputRef,并為 onFocus 和 onBlur 事件分別添加了 handleFocus 和 handleBlur 函數(shù)。在 handleFocus 函數(shù)中,我們將輸入框的背景顏色設置為黃色,在 handleBlur 函數(shù)中將其設置為白色。點擊 Focus input 按鈕時,我們使用 inputRef.current.focus() 讓輸入框聚焦。
結(jié)語
React.useRef 提供了一種在函數(shù)組件中存儲可變值和 DOM 元素引用的方法。使用 useRef 可以讓我們在函數(shù)組件中實現(xiàn)更多的功能,并且不會引起組件的重新渲染。在使用 useRef 時,需要注意不要濫用 useRef,只在必要的時候使用它,以避免造成代碼的混亂。
以上就是重新理解 React useRef的詳細內(nèi)容,更多關(guān)于重新理解 React useRef的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
React?Hooks中?useRef和useImperativeHandle的使用方式
這篇文章主要介紹了React?Hooks中?useRef和useImperativeHandle的使用方式,文中說明了useRef和useCallback一起使用,?可以解決閉包陷阱的問題,本文結(jié)合實例代碼介紹的非常詳細,需要的朋友可以參考下2023-10-10React 無狀態(tài)組件(Stateless Component) 與高階組件
這篇文章主要介紹了React 無狀態(tài)組件(Stateless Component) 與高階組件,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08