React-Hooks诞生背景
众所周知,React的组件创建方式,一种是 类组件 ,一种是 函数组件 ,并且React团队主推函数式编程,鼓励使用函数式的编程方式。也就是说React组件的推荐最佳写法应该是函数,而不是类。
但是我们知道,在实际开发中 类组件 和 纯函数组件 的区别是很大的,分别有各自的特点。纯函数组件与类组件的不同点,主要可总结为以下几点:
- 纯函数组件没有状态 State
- 纯函数组件没有生命周期钩子
- 纯函数组件没有
this
- 组件只能是纯函数
这就导致了,React 团队所推崇的函数组件,最早的时候只能做相关 UI 展示的功能,涉及到状态、数据的管理与切换,就不得不使用类组件或者 Redux 等配套工具。
但我们知道其实 React 的类组件的也是有不少缺点的:比如,遇到简单的页面和需求,你的代码会显得很笨重,并且每创建一个类组件,都要去继承一个React实例,代码书写形式比较繁琐。此外,还要小心仔细应对 this
指针,正确判断和处理this
指针所指向的对象,不然很容易引发 bug。this
指针的处理对于不少 JS 初学者是比较头疼的事情。此外还有一些在大型项目中大量使用类组件可能带来的问题:
- 大型组件很难拆分和重构,也很难测试。
- 业务逻辑分散在组件的各个方法之中,导致重复逻辑或关联逻辑。
- 组件类引入了复杂的编程模式,比如 render,props,增加复杂度。
至于配套的管理工具 Redux,很久之前 Redux 的作者就说过,“能用 React 解决的问题就不用 Redux”,诸如此类的话。一律使用 Redux 解决状态管理以及组件之间的通信问题,看起来并不是最优解。
类组件书写起来非常笨重,而函数组件相对就轻便很多。类组件书写的笨重可以用下面一个简单的例子来体现(一个简单的点击 +1 的计数器):
class Counter extends React.PureComponent {
constructor(props){
super(props)
this.state = {
count: 0
}
}
add = () => {
this.setState({
count: this.state.count +=1
})
}
render(){
return (
<>
<p>{this.state.count}</p>
<button onClick={this.add}> +1 </button>
</>
)
}
}
如果换用函数组件的写法,又是如何呢(不能做状态管理,暂时挂载在window上):
const Counter = () => {
window.count = 0
const add = () => {
window.count++
}
return (
<>
<p>{window.count}</p>
<button onClick={add}> +1 </button>
</>
)
}
看起来确实书写上轻便多了,但是由于函数组件没有状态 State 管理功能,非常粗暴地挂载在 window 下做成了全局变量,是很不合适的。
那么我们知道了纯函数书写相对很轻便,且React团队推崇尽量使用函数组件。但它却有本文开头提到的几点重大缺陷,为了弥补函数式组件的功能性,React团队设计了React Hooks这套重要的Api,它彻底改变了纯函数组件的地位,让开发者可以只使用纯函数组件 ,完全不使用类组件,就能写出一个全功能的组件。可以说,React Hooks 就是加强版的函数组件,或者更接近完全体的函数组件。
使用 React Hooks 来重写上文中的组件:
const Counter = () => {
const [count, setCount] = useState(0)
const add = () => {
setCount(count + 1)
}
return (
<>
<p>{count}</p>
<button onClick={add}> +1 </button>
</>
)
}
通过上面的代码,我们实现了一个功能一致的计数器,代码看起来非常的轻便简洁,没有了类组件的继承,没有了渲染逻辑等繁杂的设置。这就是 React hooks 存在的意义。帮助纯函数组件实现在书写轻便的同时完善功能。
后续具体的 React Hooks 组件学习心得小结,将会持续更新……