前言:自从 react16.8 推出 hooks 以来,hooks 也被越来越多的人使用,面试中也不可避免的会被问到。那么 hooks 到底是什么呢?它较于传统的 class 组件又有什么优势呢?
1.什么是 React hooks?
Hook 即为”钩⼦”, 是 react 16.8 的新特性, 你可以在不写 class 的情况下使用 state 和其他的 react 特性。凡是 use 开头的 React API 都是 Hooks, 例如 useState、useEffect、useContext等。
2.React hooks 有什么优势呢?
首先要明白的是传统的class组件到底存在哪些问题呢?
1.告别难以理解的 Class
Class 是“难以理解”的,这个说法的背后是 this 和生命周期这两个痛点。为了解决 this 可能导致的各种问题,之前用 bind、现在推崇箭头函数,本质上都是在用实践层面的约束来解决设计层面的问题。而有了Hooks之后,函数组件是不用关心 this 的问题了。
class App extends React.Component<any, any> {
handleClick2;
constructor(props) {
super(props);
this.state = {
num: 1,
title: " react study",
};
this.handleClick2 = this.handleClick1.bind(this);
}
handleClick1() {
this.setState({
num: this.state.num + 1,
});
}
handleClick3 = () => {
this.setState({
num: this.state.num + 1,
});
};
render() {
return (
<div>
<h2>Ann, {this.state.num}</h2>
{/* 在render函数里绑定this,由于bind会返回一个新函数, 所以每次⽗组件刷新都会导致⼦组件的重新刷新, 就算⼦组件的其他props没有改变。*/}
<button onClick={this.handleClick1.bind(this)}>btn1</button>
{/* 构造函数内绑定this, 每次父组件刷新的时候, 如果传递给子组件的其他 props 不变, 子组件就不会刷新。*/}
<button onClick={this.handleClick2}>btn2</button>
{/* 使用箭头函数, 每次都会生成一个新的箭头函数, 每次⽗组件刷新的时候, 如果传递给子组件的其他props不变, 子组件就不会刷新*/}
<button onClick={() => this.handleClick1()}>btn3</button>
{/* 使⽤类里定义的箭头函数, 和handleClick2原理一样, 但是⽐第⼆种更简洁*/}
<button onClick={this.handleClick3}>btn4</button>
</div>
);
}
}
至于生命周期,它带来的麻烦主要有以下两个方面: 学习成本 和 不合理的逻辑规划方式
2.能解决业务逻辑难以拆分的问题
在class组件中,逻辑曾经一度与生命周期耦合在一起。一个生命周期中可能做许多事情,比如在 componentDidMount 里获取数据,在 componentDidUpdate 里根据数据的变化去更新 DOM 等。如果说你只用一个生命周期做一件事,那好像也还可以接受,但是往往在一个稍微成规模的 React 项目中,一个生命周期不止做一件事情。还有比如设置监听, 添加定时器, 我们需要在两个生命周期⾥完成注册和销毁, 很有可能漏写导致内存泄露问题。
componentDidMount() {
const timer = setInterval(() => {});
this.setState({timer})
}
componentWillUnmount() {
if (this.state.timer) {
clearInterval(this.state.timer);
}
}
3.使状态逻辑复用变得简单可行
在 class 组件中,组件间如果有 state 的逻辑是复用的话, 基本是⽤高阶组件来解决的。虽然能够解决问题, 但是我们可能需要在组件外部再包一层元素, 会导致层级非常冗余,形成“嵌套地狱”现象。
过去我们复用状态逻辑,靠的是 HOC(高阶组件)和 Render Props 这些组件设计模式,这是因为 React 在原生层面并没有为我们提供相关的途径。但这些设计模式并非万能,它们在实现逻辑复用的同时,也破坏着组件的结构,形成“嵌套地狱”。
Hooks 可以视作是 React 为解决状态逻辑复用这个问题所提供的一个原生途径。现在我们可以通过自定义 Hook,达到既不破坏组件结构、又能够实现逻辑复用的效果。
3.react hooks 的注意事项
-
只能在函数内部的最外层调用 Hook,不要在循环、条件判断或者嵌套函数中调⽤
-
只能在 React 的函数组件中调用 Hook,不要在其他 JavaScript 函数中调⽤
参考: