Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React进阶系列之Hooks设计动机 #31

Open
campcc opened this issue Aug 23, 2021 · 0 comments
Open

React进阶系列之Hooks设计动机 #31

campcc opened this issue Aug 23, 2021 · 0 comments

Comments

@campcc
Copy link
Owner

campcc commented Aug 23, 2021

当我们由浅入深地认知一样新事物地时候,往往需要遵循 “Why-What-How” 的一个认知过程,这三者往往是相辅相成、缺一不可的。某种层面上,对于一个工程师而言,他/她对 “Why” 的执着程度,很大程度上能反映其职业天花板的高度。

Motivation

我们先从 Why 开始,聊聊 React Hooks 设计的动机。

Hooks 在 React 16.8 后被推而广之,在这之前,组件多以类组件无状态的函数组件形式为主,而 Hooks 正是 React 团队在真刀真枪的 React 组件开发实践中,逐渐认识到的一个改进点,这背后其实涉及对类组件函数组件两种组件形式的思考和侧重。因此,你首先得知道,什么是类组件、什么是函数组件,并完成这两种组件形式的辨析。

类组件

基于 ES6 Class 的写法,通过继承 React.Component、React.PureComponent 得来的 React 组件,

class Component extends React.Component {
  constructor() {
    this.state = {};
  }

  render() {
    return (
      <div>React Class Component</div>
    );
  };
}

函数组件

以函数形态存在的 React 组件,早期没有 Hooks 加持,内部无法定义和维护 state,因此它还有一个别名叫“无状态组件”,

function Component(props) {
  const { text } = props;
  return (
    <div>{text}</div>
  );
}

函数组件与类组件对比:无关“优劣”,只谈“不同”

  • 类组件需要继承 class,函数组件不需要
  • 类组件可以访问生命周期方法,函数组件不能
  • 类组件中可以获取实例化后的 this,并基于 this 做各种各样的事情,函数组件不能
  • 类组件中可以定义并维护 state 状态,函数组件不能
  • ... ...

单就我们上述列出的这几点里面,频繁出现了“类组件可以xxx,函数组件不能xxx”,是否意味着类组件比函数组件更好呢?

答案当然是否定的。只是在 Hooks 出现之前,类组件的能力边界明显强于函数组件,但我们讨论这两种组件形式,不应怀揣“孰优孰劣”这样的成见,而应该更多地去关注两者的不同,进而把不同的特性与不同的场景做连接,这样才能求得一个全面的、辩证的认知。

重新理解类组件:包裹在面向对象思想下的“重装战舰”

类组件体现了面向对象的封装和继承,内置了 state、生命周期等相当多的“现成的东西”等着你去调度、定制,而想要得到这些东西,你只需要简单地继承一个 React.Component 即可,这种感觉就好像是你不费吹灰之力,就拥有了一辆“重装战舰**。但是多就是好吗?

未必。想象一下现在你只是需要打死一只蚊子,给你一辆重装战舰,似乎也 ”可以,但没有必要“,类组件 ”大而全“的背后,是不可忽视的学习成本和心智负担,这主要体现在,

  • 编写需要理解各种复杂的姿势,比如 this 原理,生命周期
  • 组件内部的逻辑难以实现拆分和复用,想要打破僵局,则需要进一步学习更加复杂的设计模式(比如高阶组件,Render Props 等),用更高的成本来换取一点点的编码灵活度

函数组件:呼应 React 设计思想的”轻巧快艇“

毋庸置疑,函数组件更加契合 React 框架的设计理念,

image.png

React 组件本身的定位就是函数,一个吃进数据,吐出 UI 的函数,这意味着 React 的数据应该总是紧紧地和渲染绑在一起,而类组件做不到这一点,这也是两类组件最大的不同:函数组件会捕获 render 内部的状态。React 作者 Dan 早期特意为此写过一篇非常棒的对比文章, 如果你疑惑为什么类组件做不到,可以先阅读上面的文章。

假设你已经阅读完 Dan 的文章,我们不难发现其中的缘由,因为虽然 props 本身是不可变的,但 this 却是可变的,this 上的数据是可以被修改的,所以当我们通过 setTimeout 将预期的渲染推迟 3s 后,脱离了 React 生命周期对执行顺序的调控,这打破了 this.props 和渲染动作之间的这种时机上的关联,进而导致渲染时捕获了一个错误的、修改后的 this.props

但是函数组件可以做到真正的把数据和渲染绑在一起,因为父组件传入新的 props 时,本质上是基于新的 props 发起一次全新的函数调用,不会影响上一次调用对于上一个 props 的捕获。

经过岁月的洗礼,React 团队也认识到了,函数组件是一个更加匹配其设计理念、也更有利于逻辑拆分与重用的组件表达形式,所以后面用实际行动支持开发者编写函数组件,而这里的实际行动就是 Hooks。

Hooks 的本质:一套能够使函数组件更强大、更灵活的钩子

React Hooks 的出现,补齐函数组件相较于类组件缺失的能力,如果说函数组件是一台轻巧的快艇,那么 React-Hooks 就是一个内容丰富的零部件箱,而且类组件这个重装战舰里预设那些装备,这里箱子里基本全都有,关键是它还不强制你全都要,而是允许你自由地选配和使用,所以不由得感叹一句:真香!

行文至此,想必你已经深刻理解了 React Hooks 的设计动机,接下来我们将深入地理解 Hooks 的工作机制和原理。

相关文章

写在最后

本文首发于我的 博客,才疏学浅,难免有错误,文章有误之处还望不吝指正!

如果有疑问或者发现错误,可以在评论区进行提问和勘误,

如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。

(完)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant