4. React 高阶组件、Render props、hooks 有什么区别, 为什么要不断迭代?
这三者是目前 react
解决代码复用的主要方式:
- 高阶组件(
HOC
)是React
中用于复用组件逻辑的一种高级技巧。HOC
自身不是React API
的一部分, 它是一种基于React
的组合特性而形成的设计模式。具体而言, 高阶组件是参数为组件, 返回值为新组件的函数 render props
是指一种在React
组件之间使用一个值为函数的prop
共享代码的简单技术, 更具体地说,render prop
是一个用于告知组件需要渲染什么内容的函数prop
- 通常,
render props
和高阶组件只渲染一个子节点。让Hook
来服务这个使用场景更加简单。这两种模式仍有用武之地, (例如, 一个虚拟滚动条组件或许会有一个renderltem
属性, 或是一个可见的容器组件或许会有它自己的DOM
结构)。但在大部分场景下,Hook
足够了, 并且能够帮助减少嵌套
HOC 官方解释
高阶组件(HOC
)是 React
中用于复用组件逻辑的一种高级技巧。HOC
自身不是 React API
的一部分, 它是一种基于 React
的组合特性而形成的设计模式。
简言之, HOC
是一种组件的设计模式, HOC
接受一个组件和额外的参数(如果需要), 返回一个新的组件。HOC
是纯函数, 没有副作用。
// hoc的定义
function withSubscription(WrappedComponent, selectData) {
return class extends React.Component {
constructor(props) {
super(props);
this.state = {
data: selectData(DataSource, props)
};
}
// 一些通用的逻辑处理
render() {
// ... 并使用新数据渲染被包装的组件!
return <WrappedComponent data={this.state.data} {...this.props} />;
}
};
}
// 使用
const BlogPostWithSubscription = withSubscription(BlogPost, (DataSource, props) => DataSource.getBlogPost(props.id));
HOC
的优缺点:
- 优点: 逻辑服用、不影响被包裹组件的内部逻辑
- 缺点:
hoc
传递给被包裹组件的props
容易和被包裹后的组件重名, 进而被覆盖
Render props 官方解释∶
render prop
是指一种在 React
组件之间使用一个值为函数的 prop
共享代码的简单技术
具有 render prop
的组件接受一个返回 React
元素的函数, 将 render
的渲染逻辑注入到组件内部。在这里, render
的命名可以是任何其他有效的标识符。
// DataProvider组件内部的渲染逻辑如下
class DataProvider extends React.Components {
state = {
name: 'Tom'
}
render() {
return (
<div>
<p>共享数据组件自己内部的渲染逻辑</p>
{this.props.render(this.state)}
</div>
);
}
}
// 调用方式
<DataProvider render={data => (
<h1>Hello {data.name}</h1>
)}/>
由此可以看到, render props
的优缺点也很明显:
- 优点: 数据共享、代码复用, 将组件内的
state
作为props
传递给调用者, 将渲染逻辑交给调用者 - 缺点: 无法在
return
语句外访问数据、嵌套写法不够优雅
Hooks 官方解释∶
Hook
是 React 16.8
的新增特性。它可以让你在不编写 class
的情况下使用 state
以及其他的 React
特性。通过自定义 hook
, 可以复用代码逻辑。
// 自定义一个获取订阅数据的hook
function useSubscription() {
const data = DataSource.getComments();
return [data];
}
//
function CommentList(props) {
const {data} = props;
const [subData] = useSubscription();
// ...
}
// 使用
<CommentList data='hello'/>
以上可以看出, hook
解决了 hoc
的 prop
覆盖的问题, 同时使用的方式解决了 render props
的嵌套地狱的问题。hook
的优点如下∶
- 使用直观
- 解决
hoc
的prop
重名问题 - 解决
render props
因共享数据而出现嵌套地狱的问题 - 能在
return
之外使用数据的问题
需要注意的是: hook 只能在组件顶层使用, 不可在分支语句中使用。
总结∶ Hoc
、render props
和 hook
都是为了解决代码复用的问题, 但是 hoc
和 render props
都有特定的使用场景和明显的缺点。hook
是 react16.8
更新的新的 API
, 让组件逻辑复用更简洁明了, 同时也解决了 hoc
和 render props
的一些缺点。