前言

推荐阅读:# useMemo..一把梭?达咩!✋|一文告诉你为什么React不把他们设为默认方法 #useEvent 是一个刚刚提案的原生Hook,还处于RFC。讨论地址在这里~下面有些代码就是来自其中

RFC:Request for Comments 提案还在广泛的讨论阶段

没有 useEvent 的时候😶

我们先看看不用 useEvent 的情况:

function Chat() {
  const [text, setText] = useState('');
  // 🟡 Always a different function
  const onClick = () => {
    sendMessage(text);
  };
  return <SendButton onClick={onClick} />;
}

其中点击事件的回调函数 onClick 中需要读取当前键入的文本text,这里的onClick随着组件重新渲染一次次地重新创建,每次都会是不一样的引用,这显然带来了性能损耗,如果你想对其进行优化,你可能会这样做:

function Chat() {
  const [text, setText] = useState('');
  // 🟡 A different function whenever `text` changes
  const onClick = useCallback(() => {
    sendMessage(text);
  }, [text]);
  return <SendButton onClick={onClick} />;
}

通过 useCallback 返回一个 memoized 回调函数。

useCallback: 返回一个 memoized 回调函数。 把内联回调函数及依赖项数组作为参数传入 useCallback,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新。当你把回调函数传递给经过优化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate)的子组件时,它将非常有用。 useCallback(fn, deps) 相当于 useMemo(() => fn, deps)

最终使得onClick的引用始终不变但是!

onClcik这个方法有需要保证每次都要拿到最新的、正确的text,所以他的deps中就自然是设置了text—— 坏了,“又回到最初的起点~”。随着每一次keystrokeonClick又变成了上面的情况:

 Always a different function

但你又不能将其从deps中移除,移除了他就只能拿到text的初始值,失去了他本该有的功能...

小 useEvent 来给他整个活😎

useEvent就是为了解决此类问题,所以他干脆不要deps了,他就是一直返回一个相同的函数引用,哪怕text发生变化。当然,保证它也能拿到最新的、正确的**text**

function Chat() {
  const [text, setText] = useState('');
  // ✅ Always the same function (even if `text` changes)
  const onClick = useEvent(() => {
    sendMessage(text);
  });
  return <SendButton onClick={onClick} />;
}

现在好了:

  • onClick 的引用始终是同一个
  • 保证每次都能拿到最新的、正确的 text

当然还有其他一些场景,但是大致需求原理相同,就是不想让A因为b变化而总是重新加载,但是又因为要拿到b恰当的值,所以deps中必须b,导致不得不重新加载,掉进了“圈圈圆圆圈圈~”的陷阱。更多场景这里就不再赘述。更多案例可查看文末的学习资源~

总而言之,用useEvent给他裹上就是香,就是可以同时达到上面两个效果:

  • 引用不变
  • 拿到恰当的值

这是咋做到的🌝

说了这么多,我们来看看他这是咋做到的
大概是这么个形状:(不是源码就长这样的意思嗷)

// (!) Approximate behavior
function useEvent(handler) {
  const handlerRef = useRef(null);
  // In a real implementation, this would run before layout effects
  useLayoutEffect(() => {
    handlerRef.current = handler;
  });
  return useCallback((...args) => {
    // In a real implementation, this would throw if called during render
    const fn = handlerRef.current;
    return fn(...args);
  }, []);
}

先回顾几个Hook相关知识点:

useRef

useRef:

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内持续存在。

这里通过 useRef 保存回调函数handlerhandlerRef.current,然后再在 useCallback 中从handlerRef.current来取函数再调用,这样避免了直接调用,跳出了闭包陷阱。并且不出意外的话handler在整个生命周期内持续存在,也就是只有一个引用

useLayoutEffect

这个 useLayoutEffect 可能没那么常用,我们来看看这是啥嘞

其函数签名与 useEffect 相同,但它会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。

useEffect

回顾一下 useEffect

默认情况下,effect 将在每轮渲染结束后执行

两者的区别

好了,现在我给你用一个字总结一下两者区别,useLayoutEffect 更“快”!这个“块”不是速度更快,而是他“抢跑”了哩。useLayoutEffect 是在render之前同步执行,useEffectrender之后异步执行,这里就是保证useLayoutEffect 里的回调肯定比useEffect更早前被调用、被执行。

useCallback执行时机

前面说到

useCallback(fn, deps) 相当于 useMemo(() => fn, deps)

文档里是这样说 useMemo 的:

记住,传入 useMemo 的函数会在渲染期间执行。请不要在这个函数内部执行与渲染无关的操作,诸如副作用这类的操作属于 useEffect 的适用范畴,而不是 useMemo。

也就是他是在render执行的,也就是保证了赋值handlerhandlerRef.current是在前面发生

这里的作用

这里返回的是一个useCallback包裹后 memoized函数,其中从handlerRef.current中获取函数,并且deps[],也就是说他不会再次更新。

捋一捋🌊

回顾完知识点我们也就滤清了这个useEvent方法,一句话总结就是:它接收一个回调函数handler作为参数,提供给你一个稳定的函数(始终只有一个引用)并且调用时都是用的你传入的最新的参数...args——比如前面案例中的text,始终都是最新的、正确的、恰当的。再结合一开始的案例,大概流程就是这样:

不过目前这个也是 5.4号刚刚提出,也就是昨天,在正式生产环境中使用应该还早,但我希望你还是能从本文有所收获滴~

以上就是useEvent显著降低Hooks负担的原生Hook的详细内容,更多关于useEvent降低Hooks负担原生Hook的资料请关注Devmax其它相关文章!

useEvent显著降低Hooks负担的原生Hook的更多相关文章

  1. React-hooks面试考察知识点汇总小结(推荐)

    这篇文章主要介绍了React-hooks面试考察知识点汇总,Hook 使你在无需修改组件结构的情况下复用状态逻辑,本文结合示例代码给大家介绍的非常详细,需要的朋友可以参考下

  2. Vue3.2 setup语法糖及Hook函数基本使用

    这篇文章主要为大家介绍了Vue3.2 setup语法糖及Hook函数基本使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  3. React Hook用法示例详解(6个常见hook)

    这篇文章主要介绍了React Hook用法详解(6个常见hook),本文通过实例代码给大家介绍了6个常见hook,需要的朋友可以参考下

  4. 基于React Hooks的小型状态管理详解

    本文主要介绍一种基于 React Hooks 的状态共享方案,介绍其实现,并总结一下使用感受,目的是在状态管理方面提供多一种选择方式。感兴趣的小伙伴可以了解一下

  5. 详解React Hooks是如何工作的

    React Hooks是在React 16.8版本新增的特性,在我看了React官网和一些博客对React Hook的讲解后还是觉得没有get到本质。本篇博客通过手动实现useState()来了解Hook的原理和本质。阅读此篇博客的前提是你要知道一些 React Hooks的基本用法和使用规则,不然会看得云里雾里。

  6. LyScript实现Hook隐藏调试器的方法详解

    LyScript 插件集成的内置API函数可灵活的实现绕过各类反调试保护机制。本文将运用LyScript实现绕过大多数通用调试机制,实现隐藏调试器的目的,需要的可以参考一下

  7. React深入浅出分析Hooks源码

    在react类组件(class)写法中,有setState和生命周期对状态进行管理,但是在函数组件中不存在这些,故引入hooks(版本:>=16.8),使开发者在非class的情况下使用更多react特性

  8. 如何对react hooks进行单元测试的方法

    这篇文章主要介绍了如何对react hooks进行单元测试的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  9. React官方团队完善原生Hook闭包陷阱

    这篇文章主要为大家介绍了React官方团队出手,补齐原生Hook短板闭包陷阱的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. react hooks实现原理解析

    这篇文章主要介绍了react hooks实现原理,文中给大家介绍了useState dispatch 函数如何与其使用的 Function Component 进行绑定,节后实例代码给大家介绍的非常详细,需要的朋友可以参考下

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部