博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
函数化的React Hooks
阅读量:5868 次
发布时间:2019-06-19

本文共 3544 字,大约阅读时间需要 11 分钟。

写在前面

在2018年React Conf大会上,React团队讲解了目前大家使用React开发过程存在的一些问题并推出了一个令人激动的概念:React Hooks,并介绍hooks如何解决这些问题。刚好我所在的团队前端使用的是react+ts+node这套技术栈,前段时间将react版本升级到了16.8,在这个过程中使用到了hooks的功能。在这里写下自己的感受和见解。

本文将从以下几部分进行总结:

  1. React Hooks之前还存在哪些痛点?
  2. React Hooks带来的代码模式改变
  3. 总结
  4. 扩展阅读

React Hooks之前还存在哪些痛点?

1.组件间相似的逻辑复用难

在react hooks问世之前,react能提供给组件间复用逻辑采用的是mixin,但这种方式弊端非常多,所以大家基本都是用render props(渲染属性)和HOC(高阶组件)来复用组件间的逻辑。但这两种方式的缺点也是非常明显的,很容易产生「wrapper hell」,即组件很容易臃肿,增加了debugger的成本。

2.生命周期的问题

在稍微复杂的业务逻辑当中,生命周期是绕不过去的问题。有很多场景下在componentDidmount处理的逻辑不得不又在componentDidUpdate重新处理一次,业务被分散在各个不同的生命周期函数中。

而Hooks的出现,从面向生命周期编程转变为面向业务逻辑编程

3.对人以及机器都不友好的class

虽然Hooks之前可以编写纯函数组件,但它只能是无状态的。非常常见的情况是你编写了一个纯函数组件,但过一段时间你发现得加上一个状态,这时候不得不将纯函数组件改为类组件。这时候得处理this的问题,而且编译器对class也是不友好的。

React Hooks带来的代码模式改变

import { useState, useEffect } from 'react' function Example(props) {  // 声明一个新的状态变量"count"   const [count, setCount] = useState(0);  useEffect(() => {    subscribe(props.number, setCount)    return () => {      unsubscribe(props.number)    }  })  return 
{count}
}复制代码

useState会接受一个初始值,然后会返回一个[状态,状态修改器]的二元组。每次重新渲染时,整个函数会重新执行,但是useState会记住上次的值。而且react是根据useState的调用顺序来记得状态归属的:

const Example = () => {    const [size, setSize] = useState({ width: 100, height: 100 });    const [count, setCount] = useState(0);   }复制代码

每一次 Example 被渲染,都是第一次 useState 调用获得 size 和 setSize,第二次 useState 调用获得 count 和 setCount。

useEffect是用来处理副作用的,相当于以前的componentDidMount和componentDidUpdate。它可以返回一个函数,用来在组件卸载前调用。所以useEffect聚合了componentDidMount,componentDidUpdate和componentWillUnmount的操作。如果props.number没有改变,我们是不希望在useEffect订阅/取消订阅里重新执行的,为了实现这个操作,只需要传入一个参数即可。

useEffect(() => {    subscribe(props.number, setCount)    return () => {      unsubscribe(props.number)    }  }, [props.number])复制代码

它是一个数组,只要这个数组中的每一个值都不发生变化,则useEffect不需要重新执行。

在将react升级之后,生命周期函数迁移到函数组件可以按照以下方式来操作:

  • constructor: 使用 useState 来初始化 state。
  • getDerivedStateFromProps: 函数组件本身可以直接操作。
  • shouldComponentUpdate: 使用 React.memo。
  • render: 函数组件本身。
  • componentDidMount, componentDidUpdate, componentWillUnmount: 使用 useEffect 实现。

在react hooks开发的过程中,共享代码会采取函数组件的形式。约定使用useXXX开头,想重用这些代码,在函数式组件通过调用useXXX即可。

例如我们可以写这样一个useMountLog,在组件mount的时候打印出一条日志:

const useMountLog = (name) => {    useEffect(() => {        console.log(`${name} mounted`);        });}复制代码

这样一来,所有的函数式组件中都可以通过调用useMountLog来使用这个功能:

const Example = () => {    useMountLog('Example')}复制代码

再比如可以通过写useWindowWidth这样一个自定义hook来反映当前窗口的宽度

function useWindowWidth() {  const [width, setWidth] = useState(window.innerWidth);    useEffect(() => {    const handleResize = () => setWidth(window.innerWidth);    window.addEventListener('resize', handleResize);    return () => {      window.removeEventListener('resize', handleResize);    };  });    return width;}复制代码

这样就可以在其他函数式组件中使用:

function MyResponsiveComponent() {  const width = useWindowWidth();  return (    

Window width is {width}

);}复制代码

在上边的例子可以看到,react hooks大大地减少我们的代码量。而hooks只能在函数式组件中使用,所以可以预测虽然现在react仍然支持类组件,但以后类组件会慢慢得消亡。

总结

React Hooks的出现,将大大地减少react的代码量,解决原来使用react开发遇到的一些问题,也给开发带来了一些变化。包括:

  • react hooks将改变组件间重用代码的方式。使用自定义 hooks,没有 mixin 带来的混乱,没有 HOC 带来的层级深渊。
  • 从面向生命周期编程到面向业务逻辑编程
  • 不再需要class,不再需要关注this等问题

最后,引用 Dan Abramov 在React Conf 2018 上的演讲词结束本文:

“……我曾经疑惑,React 的 Logo 为什么是一个原子?后来我想到了这个解释。我们知道物质由原子组成,是原子的特性决定了物质的外观和行为。就像 React,你可以把用户视图拆成独立的组件,再像原子一样自由组合起来,是组件的特性决定了用户视图的行为。科学家们曾一度认为原子是不可分割的最小单位,直到发现了电子,一种原子内部更小的粒子。事实上,是电子的特征影响了原子的性质。我认为 hooks 就好比电子,与其说它是一个新特性,不如说是已知的 React 特性(state,context,生命周期)的更直接的展现形式,而这四年来我们却一直对它视而不见。

如果盯着 React 的 logo 看的话,你会发现 hooks 其实一直都在。”

扩展阅读

转载于:https://juejin.im/post/5cfb1e12f265da1b8a4f0f1e

你可能感兴趣的文章
国内先进的智能移动广告聚合平台-KeyMob聚合
查看>>
手机APP与原生APP设计的区别
查看>>
oa办公自动化系统怎么选择,需要注意哪些问题?
查看>>
使用 QuickBI 搭建酷炫可视化分析
查看>>
聚合支付二维码是否对商户真的有用呢?
查看>>
PCB设计中的问题整理(一)
查看>>
Java中处理二进制移位
查看>>
我的友情链接
查看>>
Python标准模块--itertools
查看>>
。。Linux。。
查看>>
关于数组做形参,用sizeof测长度的问题
查看>>
C语言单链表(不带头节点)
查看>>
程序包管理RPM、YUM及源代码编译
查看>>
CentOS下部署cobbler
查看>>
Oracle删除当前连接的用户
查看>>
linux学习笔记-文件
查看>>
linux drbd高可用集群
查看>>
python中的对象
查看>>
我的友情链接
查看>>
JMS和ActiveMQ介绍(3)_ActiveMQ
查看>>