这里有两个问题:
- React 高阶组件、Render props 和 hooks 有什么区别?
- 为什么要不断迭代?
我们先来看第一个问题,而第一个问题,要讲清楚这三者的区别,那自然要明白三者分别是什么。
React 高阶组件
高阶组件(HOC)是 React 中用于复用组件逻辑的一种技巧。其本质是:
接收一个组件作为参数,返回一个组件的函数
来看个例子就明白了:
function withSubscription(WrapperdComponent, selectData) {
return class extend React.Component {
consturctor(props) {
super(props)
this.state = {
data: selectData(DataSource, props)
}
}
render() {
return <WrapperdComponent data={this.state.data} {...this.props} />
}
}
}
高阶组件具有以下优缺点:
- 优点
- 逻辑复用
- 不影响被包裹的组件的内部逻辑
- 缺点
- 高阶组件传递给被包裹组件的 props 如果重名的话,会发生覆盖
Render props
Render props 是一种在 React 组件之间使用一个值为函数的 prop 共享代码的技术,具体来说就是:
Render prop 是一个告知组件需要渲染什么内容的函数 prop
来看个例子:
Class DataProvider extends React.Components {
state = {
name: "Alice"
}
render() {
return (
<div>
<p>共享数据组件自己内部的 render</p>
{ this.props.render(this.state) }
<div/>
)
}
}
<DataProvider render={
data => (<p>共享的 render {data.name}</>)
} />
相较于 hooks 和 hoc,render props 使用的场景较少,它具有以下优缺点:
- 优点:
- 数据共享
- 逻辑复用
- 缺点:
- 无法在 return 语句外访问数据
- 嵌套
Hooks
Hooks 是 React 16.8 中新增的特性。它可以让你在不编写 class 的情况下使用 state,lifecycle 等 React 特性。
通过自定义 hook,可以很轻松的实现逻辑复用。
我们来看个例子:
function useSubscription() {
const data = DataSource.getComments()
return [data]
}
function CommentList(props) {
const {data} = props
const [subData] = useSubscription()
return (
<div>
this is data: {data},
this is subData: {subData}
<div/>
)
}
可以看到 hooks 结构清晰明了,具有以下优点:
- 使用直观
- 不存在 hoc 的重名问题
- 不存在 render props 的嵌套问题
- 能在 return 之外访问数据
回答
现在已经明白了三者各自是什么,具有什么优缺点,那么最开始的问题就很好回答了。
React 高阶组件、Render props 和 hooks 有什么区别?
三者都能用来进行逻辑复用。区别在于高阶组件为接收组件,对其进行包装,Render props 为在 render 中渲染共享数据,而 hooks 是以函数调用的形式共享数据。
为什么要不断迭代?
在大部分情况下,高阶组件和 Render props 都存在各自的缺陷:
- 重名问题
- 嵌套问题
- 无法在 return 之外访问数据的问题
- 数据来源不清晰的问题
- ......
不断迭代是为了解决上述问题,让我们可以用更加简洁的方式实现组件逻辑复用,让写代码变得更加轻松和愉快。