首先看两段代码:
import ReactDOM from 'react-dom';
import './index.css';
import React,{useState,useEffect,useRef,createRef} from 'react';
const App = () => {
const [count, setCount] = useState(0);
const lastCount = createRef(count);
useEffect(() => {
lastCount.current = count;
})
function handleAlertClick() {
setTimeout(() => {
alert(lastCount.current)
}, 3000);
}
return <div>
<p>你点击了{count}次</p>
<button onClick={() => setCount(count + 1)}>click me</button>
<button onClick={handleAlertClick}> show Alert</button>
</div>
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
再看第二段:
import ReactDOM from 'react-dom';
import './index.css';
import React,{useState,useEffect,useRef,createRef} from 'react';
const App = () => {
const [count, setCount] = useState(0);
const lastCount = useRef(count);
useEffect(() => {
lastCount.current = count;
})
function handleAlertClick() {
setTimeout(() => {
alert(lastCount.current)
}, 3000);
}
return <div>
<p>你点击了{count}次</p>
<button onClick={() => setCount(count + 1)}>click me</button>
<button onClick={handleAlertClick}> show Alert</button>
</div>
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
页面渲染如下:
那么当多次点击第一个按钮,中途点击一下第二个按钮,然后再点击第一个按钮,弹窗弹出的数字是什么样的,解释一下流程。
两段代码的执行结果是不一样的:
首先使用了useRef的代码,我的理解是这个函数创建的lastCount对象,其指向的地址存储在函数的作用外面,也就是说函数之后再怎么执行lastCount的值不会发生变化,lastCount始终指向某一个内存地址。
再看代码,如果lastCount始终指向某个固定的内存地址,那么修改其上面的属性,不论修改多少次,当用异步方式读取时都会读取到最后一次修改的结果。
而是用createRef就不同了,调用createRef每次得到的对象都是最新的,每次得到的lastCount都是独立的,并且其存储的位置就是在函数的内部,而不是像useRef创建的lastCount存储到函数作用域外面,这样当用异步方式也就是settimeout方式读取createRef创建的lastCount时,每次读取都是读取的当前作用域的lastCount,所以每次都是不同的值,而不是最后修改的值。
类比如下代码:
for (var i = 0; i < 10; i++) {
//定义lastCount
setTimeout(() => {
console.log((i.current)
}, 3000)
}
与
for (let i = 0; i < 10; i++) {
//定义lastCount
setTimeout(() => {
console.log((i.current)
}, 3000)
}
第一段的i存储在全局,第二个i存在每个循环的单独作用域中,以上便是我对useRef和createRef的区别的理解,希望对你有所帮助。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。