React-useRef

如果我们想在hooks里面获同步取最新的值,那么则可以使用useRef, 关键源码如下:

复制代码
function mountRef<T>(initialValue: T): {|current: T|} {
  const hook = mountWorkInProgressHook();
  const ref = {current: initialValue};
  hook.memoizedState = ref;
  return ref;
}

function updateRef<T>(initialValue: T): {|current: T|} {
  const hook = updateWorkInProgressHook();
  return hook.memoizedState;
}

可以看到,代码实现非常简单,创建一个ref对象,然后挂载到hook.memoizedState, 我们在修改的时候,就是直接修改ref.current。useRef其实就是提供一个稳定的变量,在组件的整个生命周期都是持续存在且是同一个引用。
注意:修改useRef返回的状态不会引起UI的重渲染。

为什么在setTimeout的回调函数里面,拿不到useState的最新值?

主要有以下三点原因:

• react 中的state,遵循着状态不可变的原则,在setState之后,不会修改原来老的state的值,而是把新值重新赋值给hook.memoizedState。

• 对于react函数组件,其本身就是个render函数,每次重渲染之后,都会重新执行此函数,而每次执行的时候就会产生一个新的函数作用域。

• setTimeout的回调函数对hook.memoizedState形成了闭包引用,而在setState之后,都会重新执行组件函数,setTimeout 的回调函数会捕获在 setTimeout 被创建时的状态的快照,而不是最新的状态。

但是为什么又能获取useRef的最新值呢?

useRef本身并不能解决闭包引用的问题,但是它通过创建一个稳定的引用:

复制代码
function mountRef<T>(initialValue: T): {|current: T|} {
  const hook = mountWorkInProgressHook();
  const ref = {current: initialValue};
  hook.memoizedState = ref;
  return ref;
}

mount在整个组件生命周期,只会触发一次,因此只会创建一次。然后这也是为什么要创建一个对象,而对象上近仅创建一个current属性来存储数据,正是为了让开发者在整个生命周期,拿到的始终是同一个引用,可以把它想象成当前组件域下的一个全局变量了,而修改数据仅仅在这个引用上的current属性修改。

相关推荐
木易 士心几秒前
Node.js 性能诊断利器 Clinic.js:原理剖析与实战指南
开发语言·javascript·node.js
不老刘1 分钟前
深入理解 React Native 的 Metro
javascript·react native·react.js·metro
哆啦A梦15881 分钟前
67 token 过期时间
前端·javascript·vue.js·node.js
萌狼蓝天3 分钟前
[Vue]AntV1.7表格自带筛选确定和重置按钮位置交换
前端·javascript·css·vue.js·html
PitayaDog4 分钟前
(三)React19+TS基础进阶与实战完全指南
react.js
by__csdn7 分钟前
Axios封装实战:Vue2高效HTTP请求
前端·javascript·vue.js·ajax·vue·css3·html5
匠心网络科技10 分钟前
前端框架-框架为何应运而生?
前端·javascript·vue.js·学习
没文化的程序猿13 分钟前
高效获取 Noon 商品详情:从数据抓取到业务应用全流程手册
前端·javascript·html
mn_kw14 分钟前
Spark SQL CBO(基于成本的优化器)参数深度解析
前端·sql·spark