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系列(一)— Hook背景、介绍,与Render props和高阶组件比较 #64

Open
LightXJ opened this issue Jul 12, 2020 · 0 comments

Comments

@LightXJ
Copy link
Owner

LightXJ commented Jul 12, 2020

ReactHook基本概念

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性

从官网的这句话中,我们可以明确的知道,Hook增加了函数式组件中state的使用,在之前函数式组件是无法拥有自己的状态,只能通过props以及context来渲染自己的UI,而在业务逻辑中,有些场景必须要使用到state,那么我们就只能将函数式组件定义为class组件。而现在通过Hook,我们可以轻松的在函数式组件中维护我们的状态,不需要更改为class组件。

React Hooks要解决的问题是状态共享,这里的状态共享是指共享状态逻辑复用,并不是指数据之间的共享。我们知道在React Hooks之前,解决状态逻辑复用问题,我们通常使用higher-order components和render-props,那么既然已经有了这两种解决方案,为什么React开发者还要引入React Hook?对于higher-order components和render-props,React Hook的优势在哪?

React Hook动机

React Hook是官网提出的又一种全新的解决方案,我们先看一下React Hook提出的动机

  1. 在组件之间复用状态逻辑很难
  2. 复杂组件变得难以理解
  3. 难以理解的 class

下面说说我对这三个动机的理解:
在组件之间复用状态逻辑很难
在之前,我们通过高阶组件(Higher-Order Components)和渲染属性(Render Props)来解决状态逻辑复用困难的问题。很多库都使用这些模式来复用状态逻辑,比如我们常用redux、React Router。高阶组件、渲染属性都是通过组合来一层层的嵌套共用组件,这会大大增加我们代码的层级关系,导致层级的嵌套过于夸张。从React的devtool我们可以清楚的看到,使用这两种模式导致的层级嵌套程度
render Props

image

高阶组件
image

对于高阶组件来说,如果你没有对组件手动设置 name/displayName,就会遇到更严重的问题,那就是一个个匿名组件嵌套。毕竟上面 render props 的嵌套至少能知道组件名。

复杂组件变得难以理解
在不断变化的业务需求中,组件逐渐会被状态逻辑以及副作用充斥,每个生命周期常常会包含一些不相关的逻辑。我们写代码通常都依据函数的单一原则,一个函数一般只处理一件事,但在生命周期钩子函数中通常会同时做很多事情。比如,在我们需要在componentDidMount中发起ajax请求获取数据,同时有时候也会把事件绑定写在此生命周期中,甚至有时候需要在componentWillReceiveProps中对数据进行跟componentDidMount一样的处理。

难以理解的class
个人觉得使用class组件这种还是可以的,只要了解了class的this指向绑定问题,其实上手的难度不大。大家要理解,这并不是 React 特有的行为;这其实与 JavaScript 函数工作原理有关。所以只要了解好JS函数工作原理,其实this绑定都不是事。只是有时候为了保证this的指向正确,我们通常会写很多代码来绑定this,如果忘记绑定的话,就有会各种bug。绑定this方法:

1.this.handleClick = this.handleClick.bind(this);
2.<button onClick={(e) => this.handleClick(e)}>
   Click me
 </button>

于是为了解决以上问题,React Hook就被提出来了

React Hook例子

import { useState } from 'React';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);


  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

我们再来看看不用React Hook的话,如何实现

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

可以看到,在React Hook中,class Example组件变成了函数式组件,但是这个函数式组件却拥有的自己的状态,同时还可以更新自身的状态。这一切都得益于useState这个Hook,useState 会返回一对值:当前状态和一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数。它类似 class 组件的 this.setState,但是它不会把新的 state 和旧的 state 进行合并。

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