【发布时间】:2018-07-07 14:15:50
【问题描述】:
似乎render props 到目前为止还没有得到足够的关注,但是,它被著名的 React 库广泛使用,例如 react-router 4、react motion 等。而且 React 站点也有一个专门的部分,任何理由这种出现的模式,与众所周知的 HOC(高阶组件)模式相比如何?
【问题讨论】:
似乎render props 到目前为止还没有得到足够的关注,但是,它被著名的 React 库广泛使用,例如 react-router 4、react motion 等。而且 React 站点也有一个专门的部分,任何理由这种出现的模式,与众所周知的 HOC(高阶组件)模式相比如何?
【问题讨论】:
为我的研究留下答案,非常欢迎不同的答案和讨论!
HOC 借鉴了High Order Function 的概念:
高阶函数(也称为泛函、泛函形式或函子)是至少执行以下操作之一的函数:
- 将一个或多个函数作为参数(即过程参数),
- 返回一个函数作为其结果。[有争议 - 讨论]
高阶组件 (HOC) 是 React 中用于重用组件逻辑的高级技术。
源自Gist。
这个模式是关于STATIC组合的。核心/可重用逻辑封装在 HOC 中,而将活动部分留给组件。
以 react 路由器中的withRouter 为例:
withRouter 将在渲染时将更新的匹配、位置和历史道具传递给包装的组件。
// 这绕过了 shouldComponentUpdate
withRouter(connect(...)(MyComponent))
现在你得到一个增强的 MyComponent 回来,它有由路由器 HOC 传递的 { history, match, location, ...connectProps, ...ownProps } 的 props。
一种常见的方法是
compose(
connect( ... ),
enhance( ... ),
withRouter( ... ),
lifecycle( ... ),
somethingElse( ... )
)(MyComponent);
最重要的是,您可以使用compose utility 无限组合这些 HOC,以获得组件的最终增强版本,并且您的组件将从 HOC 返回的新组件中获得有关 redux 存储、反应路由器等的知识.
这种方法的缺点是:
组件的行为是在运行时之前定义的,因此失去了 react 渲染生命周期的能力,比如你不能这样做:
compose(
this.state.shouldConnect && connect( ... ),
this.state.shouldEnhance && enhance( ... ),
this.state.shouldWithRouter && withRouter( ... ),
...
)(MyComponent);
因为state/props 在您的代码运行之前不可用。
间接和命名冲突。
将 HOC 与 ES6 类一起使用会带来许多与 mixin 与 createClass 相同的问题,只是重新安排了一下。
HOC 引入了很多仪式,因为它们包装组件并创建新组件,而不是混入现有组件中。
渲染道具是组件用来知道要渲染什么的函数道具。
首先被react-motion 采用,早在Dan's Gist 首次提交redux 前几周看到。
这个模式是关于DYNAMIC组合的。核心/可重用逻辑保留在组件中,而移动部分作为回调属性传递。
您可以通过渲染道具创建 HOC。
还是以withRouter为例:
const withRouter = Component => {
const C = props => {
const { wrappedComponentRef, ...remainingProps } = props;
return (
<Route
render={routeComponentProps => (
<Component
{...remainingProps}
{...routeComponentProps}
ref={wrappedComponentRef}
/>
)}
/>
);
};
...
return hoistStatics(C, Component);
};
反之则不然。
<Connect render={connectPropsMergedWithState => {
<Enhance render={enhancePropsMergedWithState => {
<WithRouter render={routerPropsMergedWithState => {
<Lifecycle render={lifecyclePropsMergedWithState => {
<SomethingElse render={somethingElsePropsMergedWithState => {
...
}/>
...
}/>
...
}/>
...
}/>
...
}/>
虽然看起来不太好,但收获不少。
state/props)来渲染道具。众所周知的缺点是performance optimization is tricky,因为要接收的道具被推迟到运行时。过早进行优化可能不是一个好主意,但这可能完全是另一个话题。
如果你同意 react router 从 3 到 4 的方向移动,render props 可能是你的问题。
【讨论】: