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

相关推荐
JinSo7 分钟前
pnpm monorepo 联调:告别 --global 参数
前端·github·代码规范
程序员码歌14 分钟前
豆包Seedream4.0深度体验:p图美化与文生图创作
android·前端·后端
urhero18 分钟前
工作事项管理小工具——HTML版
前端·html·实用工具·工作事项跟踪·任务跟踪小工具·本地小程序
二十雨辰20 分钟前
eduAi-智能体创意平台
前端·vue.js
golang学习记28 分钟前
从0死磕全栈之Next.js connection() 函数详解:强制动态渲染的正确姿势(附实战案例)
前端
郝学胜-神的一滴35 分钟前
Three.js光照技术详解:为3D场景注入灵魂
开发语言·前端·javascript·3d·web3·webgl
m0dw39 分钟前
vue懒加载
前端·javascript·vue.js·typescript
国家不保护废物1 小时前
手写 Vue Router,揭秘路由背后的魔法!🔮
前端·vue.js
菜鸟‍1 小时前
【前端学习】仿Deepseek官网AI聊天网站React
前端·学习·react.js
小光学长2 小时前
基于Vue的保护动物信息管理系统r7zl6b88 (程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
前端·数据库·vue.js