自 React 16.8 发布以后,在已有项目中,把 package.json 中的 react 和 react-dom 版本一升,就可以抄起 Hooks 开干了。笔者目前已经在项目中开始了实操,但不妨先总结下官方文档中一些值得梳理的点。

useState

为什么 useState 不叫 createState 呢?

  • 初始渲染时,useState 返回的是 initState
  • 下次渲染时,useState 返回的是 curState

也就是说,create 的叫法就不太符合初始渲染之后获取到的是「当前状态」这么一个事实了。

为什么 useState 不通过 this 也知道自己是哪个 Component 的状态?

每个组件内部都有一个「内存格子」的列表,他们就是一些存放数据的 JS 对象,当我们使用如 useState 的 Hooks 时,就会去读取当前的格子(或者在初始渲染的时候进行初始化),然后将指针移动到下一个 Hooks。这就是为什么一个组件内部的多个 useState 都能获取到各自的局部状态。

但是需要注意的是,这也是为什么官方建议我们要将 hooks 的调用顺序保持一致。

useEffect

和过去的生命周期有什么区别?

其一,React 会在每次渲染完成后会调用 useEffect,如果使用传统的生命周期钩子的话,当我们希望每次 render 后执行某种副作用时,我们不得不在 componentDidMount 和 componentDidUpdate 里都塞上相同的逻辑,带来冗余。因此,传统的生命周期是不能代替 useEffect 的。这一点可参考 React Class 生命周期。

当然,相比较考虑 mount 和 update,只考虑 render 是要简单清晰不少。

其二,Hooks 让我们可以基于逻辑而拆分代码,而不是基于生命周期。这一点非常重要,因为基于生命周期来拆分代码,势必让逻辑相关联的代码分散各处。使用 Hooks,我们就可以按照我们指定的顺序使用每一个副作用。

传入的函数每次 render 都是新的?

是的,这是为了保证在 useEffect 中使用到的内部状态都是最新的。这样 useEffect 就很像是 render 的一部分了 —— 每次使用的 useEffect 都属于其对应的的 render。

不仅如此,我们在 useEffect 中 return 的方法,也即通常用来做取消订阅这类 cleanup 工作的,每次 render 后也都会执行一次新的副作用(准确的说会先走 return 的方法,再重新走一次 useEffect 中的方法),而绝不是 unmount 的时候才执行一次。这种模式会有更少的 bug。

什么样的 bug 呢?可以看官方文档的例子,大致就是说,如果我们订阅的人的 id 变了,就需要取消订阅然后重新订阅新的人。这样一来,如果在使用 class 做订阅这类处理时,就需要在 3 个生命周期(componentDidMount、componentDidUpdate、componentWillUnmount)里散布逻辑,即在 componentDidUpdate 补充上取消并重新订阅的逻辑!

如果用了 useEffect,这些东西根本不需要去考虑。整个过程如文档中给的例子一样依次执行:

function FriendStatus(props) {// ...useEffect(() => {ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);return () => {ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);};});// ...
}// Mount with { friend: { id: 100 } } props
ChatAPI.subscribeToFriendStatus(100, handleStatusChange);     // Run first effect// Update with { friend: { id: 200 } } props
ChatAPI.unsubscribeFromFriendStatus(100, handleStatusChange); // Clean up previous effect
ChatAPI.subscribeToFriendStatus(200, handleStatusChange);     // Run next effect// Update with { friend: { id: 300 } } props
ChatAPI.unsubscribeFromFriendStatus(200, handleStatusChange); // Clean up previous effect
ChatAPI.subscribeToFriendStatus(300, handleStatusChange);     // Run next effect// Unmount
ChatAPI.unsubscribeFromFriendStatus(300, handleStatusChange); // Clean up last effect

useEffect 第二个参数的优化作用

对 return 的 cleanup 同样适用,不要忘了,每次 render 完就会先执行一次 cleanup,最终 unmount 的时候也会执行一次 cleanup。

useEffect(() => {ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);return () => {ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);};
}, [props.friend.id]); // 只会在 props.friend.id 变化的时候重新订阅

如果我们不提供该参数,每次更新都会重新执行;如果只想 mount 和 unmount 的时候各执行一次,可指定 [],但这不是好的实践方式,考虑到 useEffect 都是在 render 完后执行的,多做点工作可能会少点问题。

Hooks 使用原则

Only Call Hooks at the Top Level. Don’t call Hooks inside loops, conditions, or nested functions.

这一条的原因是,Hooks 是通过调用顺序分配存放位置的,只有每次 run 的时候顺序保持一致,才能挨个取得正确的 useState、useEffect。比方说,如果我们把 Hooks 放到条件语句里,然后第一次 render 的时候每个都执行,第二次 render 却有一个 Hook 不执行,那么后面的对应就出错了。很好理解吧。

但如果我们一定要有条件的执行 useEffect 呢?我们可以在 useEffect 内部加条件

  useEffect(function persistForm() {// ? 这样就不会破坏第一条原则if (name !== '') {localStorage.setItem('formData', name);}});

Only Call Hooks from React Functions.

这条没什么说的,总之只在下面两处用 Hooks:

  • ✅ Call Hooks from React function components.
  • ✅ Call Hooks from custom Hooks.

React Hooks 梳理相关推荐

  1. React Hooks (一文看懂四个常用的钩子)

    React Hooks (一文看懂四个常用的钩子) 上次看了阮一峰老师的文章,写的很通俗易懂,我在这简单给大家梳理一下 我们在开发中常用的就以下四个Hooks. useState() useConte ...

  2. 浅析React Hooks原理

    React Hooks 简介 React Hooks 是 React 16.8 以及之后版本的产物,React Hooks 就是一堆钩子函数,不同的钩子函数提供了不同的功能,React 通过这些钩子函 ...

  3. react hooks使用_为什么要使用React Hooks?

    react hooks使用 The first thing you should do whenever you're about to learn something new is ask your ...

  4. react hooks使用_如何使用React和Hooks检测外部点击

    react hooks使用 by Andrei Cacio 通过安德烈·卡西奥(Andrei Cacio) 如何使用React和Hooks检测外部点击 (How to detect an outsid ...

  5. react hooks使用_如何使用Hooks将React类组件转换为功能组件

    react hooks使用 by Balaganesh Damodaran 通过Balaganesh Damodaran 如何使用Hooks将React类组件转换为功能组件 (How to conve ...

  6. 探React Hooks

    前言 众所周知,hooks在 React@16.8 中已经正式发布了.而下周周会,我们团队有个同学将会仔细介绍分享一下hooks.最近网上呢有不少hooks的文章,这不免激起了我自己的好奇心,想先行探 ...

  7. 使用React Hooks你可能会忽视的作用域问题

    前言 其实React Hooks已经推出来一段时间了,直到前一阵子才去尝试了下,看到的一些博客都是以API的使用居多,还有一些是对于原理的解析.而我这篇文章想写的是关于React Hooks使用中的作 ...

  8. dw按钮图片滚动js_使用 React Hooks 实现仿石墨的图片预览插件(巨详细)

    点击上方"前端教程",选择"星标" 每天前端开发干货第一时间送达! 作者:DARRELL https://juejin.im/post/5e9bf299f265 ...

  9. 通过 React Hooks 声明式地使用 setInterval

    2019独角兽企业重金招聘Python工程师标准>>> 本文由云+社区发表 作者:Dan Abramov 接触 React Hooks 一定时间的你,也许会碰到一个神奇的问题: se ...

最新文章

  1. w3cschool教程 - jQuery插件总结
  2. Qt实现Matlab的等差函数linSpace
  3. OkHttp3源码解析(三)——连接池复用
  4. Hi3516A开发--apt-get更新
  5. linux中rpm、yum、apt-get的关系
  6. select count(*) from返回的类型_数据分析面试题类型汇总
  7. 【uva 1395】Slim Span(图论--最小生成树+结构体快速赋值 模版题)
  8. 标准C程序设计七---72
  9. LA 5031 图询问
  10. Hadoop启动jobhistoryserver
  11. python数字图像处理(9):直方图与均衡化
  12. php实现 合唱队形(算法想清楚在动)
  13. 铁威马NAS设备映射到外网进行访问
  14. 关于当前安全设置不允许下载文件问题的解决
  15. 《打造高可用监控系统》之——Prometheus使用TIKV进行远程读(remote_read)和远程写(remote_write)
  16. Laravel Eloquent 关联
  17. 京东1.8联合会员腾讯视频QQ音乐转手教程 京东app换绑
  18. 抱怨其实是对自己的不满
  19. 【Node.js】写一个数据自动整理成表格的脚本
  20. CATT eCATT

热门文章

  1. lookup函数和vlookup_VLOOKUP和LOOKUP两个函数PK,哪个才是你心目中的查找之王?
  2. layui模板引擎laytpl判断为null或为空
  3. 技术分析在于少而精,多则惑
  4. 声智科技完成B轮2亿元融资,AI方案遍布百度小米华为阿里产品
  5. 程序猿,这里有你想学的10门机器学习课程 | 资源
  6. TensorFlow 1.11.0正式版发布了,强力支持Keras
  7. 吴恩达新书手稿完工,现在开放免费下载 | 资源
  8. 震惊!腾讯要建AI鹅厂,百度让狗刷脸购物,锤子R-1真机披露
  9. iptables的详细介绍及配置方法
  10. 《脱颖而出——成功网店经营之道》一2.5 后方——不可忽视的金库