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

相关推荐
YeeWang7 分钟前
🎉 Eficy 让你的 Cherry Studio 直接生成可预览的 React 页面
前端·javascript
gnip9 分钟前
Jenkins部署前端项目实战方案
前端·javascript·架构
Orange30151124 分钟前
《深入源码理解webpack构建流程》
前端·javascript·webpack·typescript·node.js·es6
lovepenny1 小时前
Failed to resolve entry for package "js-demo-tools". The package may have ......
前端·npm
超凌1 小时前
threejs 创建了10w条THREE.Line,销毁数据,等待了10秒
前端
车厘小团子1 小时前
🎨 前端多主题最佳实践:用 Less Map + generate-css 打造自动化主题系统
前端·架构·less
芒果1251 小时前
SVG图片通过img引入修改颜色
前端
Bug改不动了1 小时前
React Native 与 UniApp 对比
react native·react.js·uni-app
海云前端11 小时前
前端面试ai对话聊天通信怎么实现?面试实际经验
前端
一枚前端小能手2 小时前
🔧 半夜被Bug叫醒的痛苦,错误监控帮你早发现
前端