React Hooks | 青训营笔记

60 阅读3分钟

这是我参与「第五届青训营 」笔记创作活动的第 7 天

为什么需要Hook

Hook 是 React 16.8 的新增特性,它可以让我们在不编写class的情况下使用state以及其他的React特性(比如生命周期)。

class组件相对于函数式组件有什么优势?

  • class组件可以定义自己的state,用来保存组件自己内部的状态;函数式组件不可以,因为函数每次调用都会产生新的临时变量

  • class组件有自己的生命周期,可以在对应的生命周期中完成自己的逻辑;在hooks之前,如果在函数式组件中发送网络请求,意味着每次重新渲染都会重新发送一次网络请求

  • class组件可以在状态改变时只重新执行render函数以及生命周期函数,而函数式组件在重新渲染时,整个函数都会被执行

Class组件存在的问题

复杂组件变得难以理解:

随着业务的增多,class组件会变得越来越复杂, 比如componentDidMount中,可能就会包含大量的逻辑代码

export class CounterClass extends PureComponent {
  constructor(props) {
    super(props);

    this.state = {
      counter: 0,
    };
  }

  increment() {
    this.setState({
      counter: this.state.counter + 1,
    });
  }

  decrement() {
    this.setState({
      counter: this.state.counter - 1,
    });
  }

  render() {
    const { counter } = this.state;

    return (
      <div>
        <h2>当前计数: {counter}</h2>
        <button onClick={(e) => this.increment()}>+1</button>
        <button onClick={(e) => this.decrement()}>-1</button>
      </div>
    );
  }
}

包括网络请求、一些事件的监听(还需要在componentWillUnmount 中移除),而这样的class实际上非常难以拆分:因为它们的逻辑往往混在一起,强行拆分反而会造成过度设计,增加代码的复杂度。

组件复用状态很难:

为了实现一些状态的复用通常需要使用高阶组件

  • redux中connect或react-router中的withRouter,这些高阶组件设计的目的就是为了状态的复用
  • 当使用Provider、Consumer来共享一些状态时,多次使用Consumer,代码就会存在很多嵌套
  • 这些代码不管是编写和设计上来说,都非常困难

Hook的出现

Hook的出现,可以解决上面提到的这些问题

function CounterHook(props) {
  const [counter, setCounter] = useState(0);
  const [name] = useState("why");
  console.log(name);



  return (
    <div>
      <h2>当前计数: {counter}</h2>
      <button onClick={(e) => setCounter(counter + 1)}>+1</button>
      <button onClick={(e) => setCounter(counter - 1)}>-1</button>
    </div>
  );
}

简单总结一下hooks:

它可以让我们在不编写class的情况下使用state以及其他的React特性,同时,可以由此延伸出非常多的用法,来解决上面提到的问题

Hook的使用场景:

Hook的出现基本可以代替所有使用class组件的地方,如果是一个旧的项目,并不需要直接将所有的代码重构为Hooks,因为Hooks完全向下兼容,可以渐进式的来使用它,但Hook只能在函数组件中使用,不能在类组件,或函数组件之外的地方使用
Hook 是:

  • 完全可选的:你无需重写任何已有代码就可以在一些组件中尝试 Hook。但是如果你不想,你不必现在就去学习或使用 Hook。

  • 100% 向后兼容的:Hook 不包含任何破坏性改动。

  • 现在可用:Hook 已发布于 v16.8.0。

总结

Hook 就是 JavaScript 函数,这个函数可以帮助你 钩入(hook into) React State以及生命周期等特性。

但是使用它会有两个额外的规则:

  • 只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。
  • 只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用

可以看到:

函数式组件结合hooks能让整个代码变得非常简洁,并且也不用考虑this相关的问题