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

相关推荐
xixingzhe21 分钟前
Nginx 配置多个监听端口
服务器·前端·nginx
程序员Bears18 分钟前
从零打造个人博客静态页面与TodoList应用:前端开发实战指南
java·javascript·css·html5
清风细雨_林木木1 小时前
Vue 2 项目中配置 Tailwind CSS 和 Font Awesome 的最佳实践
前端·css·vue.js
逊嘘1 小时前
【Web前端开发】CSS基础
前端·css
小宁爱Python1 小时前
深入掌握CSS Flex布局:从原理到实战
前端·javascript·css
Attacking-Coder1 小时前
前端面试宝典---webpack面试题
前端·面试·webpack
极小狐2 小时前
极狐GitLab 容器镜像仓库功能介绍
java·前端·数据库·npm·gitlab
程序猿阿伟2 小时前
《Flutter社交应用暗黑奥秘:模式适配与色彩的艺术》
前端·flutter
rafael(一只小鱼)2 小时前
黑马点评实战笔记
前端·firefox
weifont2 小时前
React中的useSyncExternalStore使用
前端·javascript·react.js