本文正在参加「金石计划」
概念
-
复用组件逻辑,基于 React 的组合特性而形成的设计模式
-
高阶组件是参数为组件,返回值为新组件的函数
const EnhancedComponent = higherOrderComponent(WrappedComponent); -
Redux 的 connect 和 Relay 的 createFragmentContainer
-
无法使用组件复用逻辑时使用高阶组件
-
HOC 不会修改传入的组件,也不会使用继承来复制其行为
-
HOC 是纯函数,没有副作用
-
被包装组件接收来自容器组件的所有 prop
-
HOC 不需要关心数据的使用方式或原因,而被包装组件也不需要关心数据是怎么来的
-
可以根据需要对参数进行修改
-
不要在HOC里面使用包裹组件的相关逻辑,而应该使用组合
约定
-
HOC 应该透传与自身无关的 props
-
最大化可组合性
-
定义另一个返回高阶组件的高阶函数
// React Redux 的 `connect` 函数 const ConnectedComment = connect(commentSelector, commentActions)(CommentList); // connect 是一个函数,它的返回值为另外一个函数。 const enhance = connect(commentListSelector, commentListActions); // 返回值为 HOC,它会返回已经连接 Redux store 的组件 const ConnectedComment = enhance(CommentList); -
输出类型与输入类型相同的函数很容易组合在一起
// 不推荐如下写法... const EnhancedComponent = withRouter(connect(commentSelector)(WrappedComponent)) // ... 建议编写组合工具函数 // compose(f, g, h) 等同于 (...args) => f(g(h(...args))) const enhance = compose( // 这些都是单参数的 HOC withRouter, connect(commentSelector) ) const EnhancedComponent = enhance(WrappedComponent)
-
-
HOC命名规则,组件名(包裹组件名称)
function withSubscription(WrappedComponent) { class WithSubscription extends React.Component {/* ... */} WithSubscription.displayName = `WithSubscription(${getDisplayName(WrappedComponent)})`; return WithSubscription; } function getDisplayName(WrappedComponent) { return WrappedComponent.displayName || WrappedComponent.name || 'Component'; }
注意事项
-
复制静态方法
-
把静态方法拷贝到容器组件
function enhance(WrappedComponent) { class Enhance extends React.Component { /*…*/ } // 必须准确知道应该拷贝哪些方法 Enhance.staticMethod = WrappedComponent.staticMethod; return Enhance; } -
import hoistNonReactStatic from 'hoist-non-react-statics'; function enhance(WrappedComponent) { class Enhance extends React.Component {/*...*/} hoistNonReactStatic(Enhance, WrappedComponent); return Enhance; } -
额外导出静态方法
// 使用这种方式代替... MyComponent.someFunction = someFunction; export default MyComponent; // ...单独导出该方法... export { someFunction }; // ...并在要使用的组件中,import 它们 import MyComponent, { someFunction } from './MyComponent.js';
-
-
Refs 不会被传递
ref 添加到 HOC 的返回组件中,则 ref 引用指向容器组件,而不是被包装组件