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属性修改。

相关推荐
何何____11 小时前
js常见继承方法详解
前端·javascript
parade岁月11 小时前
Tailwind CSS 加入 Shopify,正在用 Tailwind 的项目要不要调整?
前端
梨想橙汁11 小时前
Vue2 快速入门:环境搭建、模板语法、指令系统全解
前端·vue.js
King of fraud12 小时前
HTML 页面的 CSS 选择器详解
前端·css·html
xiaoyan201512 小时前
2026最新款Electron41+React19+AntDesign电脑端后台管理系统Exe
react.js·electron·vite
前端 贾公子12 小时前
Milvus使用指南 (下)
java·服务器·前端
用户24620358278112 小时前
TypeScript类型建模与前后端错误码协议:手机号绑定场景的工程实践
前端
风骏时光牛马12 小时前
云原生架构设计:弹性底座驱动业务持续迭代
前端
用户542778485154012 小时前
浏览器后台休眠节流
前端
蜡台12 小时前
Vue 3 原生 ESM 开发实战:不用打包工具,从零搭建组件化应用
前端·javascript·vue.js·html