Ref
React提供了一個屬性ref,用於表示對組價實例的引用,其實就是ReactDOM.render()返回的組件實例:
- ReactDOM.render()渲染組件時返回的是組件實例;
- 渲染dom元素時,返回是具體的dom節點。
ref
可以掛載到組件上也可以是dom元素上;
- 掛到組件(class聲明的組件)上的ref表示對組件實例的引用。不能在函數式組件上使用 ref 屬性,因爲它們沒有實例:
- 掛載到dom元素上時表示具體的dom元素節點。
useRef()
useRef
這個hooks函數,除了傳統的用法之外,它還可以“跨渲染週期”保存數據。
首先來看一下它傳統的用法:
import React, { useState, useEffect, useMemo, useRef } from 'react';
export default function App(props){
const [count, setCount] = useState(0);
const doubleCount = useMemo(() => {
return 2 * count;
}, [count]);
const couterRef = useRef();
useEffect(() => {
document.title = `The value is ${count}`;
console.log(couterRef.current);
}, [count]);
return (
<>
<button ref={couterRef} onClick={() => {setCount(count + 1)}}>Count: {count}, double: {doubleCount}</button>
</>
);
}
代碼中用useRef
創建了couterRef
對象,並將其賦給了button的ref屬性。這樣,通過訪問couterRef.current
就可以訪問到button對應的DOM對象。
然後再來看看它保存數據的用法。
在一個組件中有什麼東西可以跨渲染週期,也就是在組件被多次渲染之後依舊不變的屬性?第一個想到的應該是state
。沒錯,一個組件的state
可以在多次渲染之後依舊不變。但是,state
的問題在於一旦修改了它就會造成組件的重新渲染。
那麼這個時候就可以使用useRef
來跨越渲染週期存儲數據,而且對它修改也不會引起組件渲染。
import React, { useState, useEffect, useMemo, useRef } from 'react';
export default function App(props){
const [count, setCount] = useState(0);
const doubleCount = useMemo(() => {
return 2 * count;
}, [count]);
const timerID = useRef();
useEffect(() => {
timerID.current = setInterval(()=>{
setCount(count => count + 1);
}, 1000);
}, []);
useEffect(()=>{
if(count > 10){
clearInterval(timerID.current);
}
});
return (
<>
<button ref={timerID} onClick={() => {setCount(count + 1)}}>Count: {count}, double: {doubleCount}</button>
</>
);
}
在上面的例子中,我用ref
對象的current
屬性來存儲定時器的ID,這樣便可以在多次渲染之後依舊保存定時器ID,從而能正常清除定時器。
參考資料:
- React之ref:https://www.jianshu.com/p/56ace3e7f565
- React—useRef:https://blog.csdn.net/hjc256/article/details/102587037