一、高阶组件是什么?
高阶组件(HOC)是一个接管组件作为参数并返回新组件的函数。将多个组件的雷同逻辑代码,形象到HOC中,让组件更有结构化,更易于复用。HOC不毁坏传入组件的个性,只通过组合造成新组件。HOC是纯函数,没有副作用。
二、高阶组件实例
承受了组件WrappedComponent,减少了订阅和数据刷新的操作。
// 此函数接管一个组件...function withSubscription(WrappedComponent, selectData) { // ...并返回另一个组件... return class extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = { data: selectData(DataSource, props) }; } componentDidMount() { // ...负责订阅相干的操作... DataSource.addChangeListener(this.handleChange); } componentWillUnmount() { DataSource.removeChangeListener(this.handleChange); } handleChange() { this.setState({ data: selectData(DataSource, this.props) }); } render() { // ... 并应用新数据渲染被包装的组件! // 请留神,咱们可能还会传递其余属性 return <WrappedComponent data={this.state.data} {...this.props} />; } };}
想要减少订阅和数据刷新性能的组件,都能够应用withSubscription,调用如下:
const CommentListWithSubscription = withSubscription( CommentList, (DataSource) => DataSource.getComments());const BlogPostWithSubscription = withSubscription( BlogPost, (DataSource, props) => DataSource.getBlogPost(props.id));
三、只组合,不毁坏原组件
1、谬误:曾经毁坏
function logProps(InputComponent) { InputComponent.prototype.componentDidUpdate = function (prevProps) { console.log('Current props: ', this.props); console.log('Previous props: ', prevProps); }; // 返回原始的 input 组件,暗示它曾经被批改。 return InputComponent;}// 每次调用 logProps 时,加强组件都会有 log 输入。const EnhancedComponent = logProps(InputComponent);
2、正确:组合组件
function logProps(WrappedComponent) { return class extends React.Component { componentDidUpdate(prevProps) { console.log('Current props: ', this.props); console.log('Previous props: ', prevProps); } render() { // 将 input 组件包装在容器中,而不对其进行批改。Good! return <WrappedComponent {...this.props} />; } }}
四、类似接口
HOC 返回的组件与原组件应放弃相似的接口。
render() { const { extraProp, ...passThroughProps } = this.props; const injectedProp = someStateOrInstanceMethod; return ( <WrappedComponent injectedProp={injectedProp} {...passThroughProps} /> );}
五、HOC不便调试
用HOC包裹组件,加上HOC和组件的名字,调试时输入,不便精确定位bug地位。
function withSubscription(WrappedComponent) { class WithSubscription extends React.Component {/* ... */ } WithSubscription.displayName = `WithSubscription(${getDisplayName(WrappedComponent)})`; return WithSubscription;}function getDisplayName(WrappedComponent) { return WrappedComponent.displayName || WrappedComponent.name || 'Component';}
六、render()中禁止应用HOC
在render办法中应用HOC,每一次HOC都会产生一个新组件,使得原来组件被卸载,再从新加载新组件,这不仅仅是性能问题 - 从新挂载组件会导致该组件及其所有子组件的状态失落。
render() { // 每次调用 render 函数都会创立一个新的 EnhancedComponent // EnhancedComponent1 !== EnhancedComponent2 const EnhancedComponent = enhance(MyComponent); // 这将导致子树每次渲染都会进行卸载,和从新挂载的操作! return <EnhancedComponent />;}
七、静态方法与HOC
用HOC包裹原组件,造成新组件,将不能拜访原始组件的静态方法。
// 定义动态函数WrappedComponent.staticMethod = function() {/*...*/}// 当初应用 HOCconst EnhancedComponent = enhance(WrappedComponent);// 加强组件没有 staticMethodtypeof EnhancedComponent.staticMethod === 'undefined' // true
能够通过上面这个计划解决:
// 应用这种形式代替...MyComponent.someFunction = someFunction;export default MyComponent;// ...独自导出该办法...export { someFunction };// ...并在要应用的组件中,import 它们import MyComponent, { someFunction } from './MyComponent.js';
八、参考链接:
- React的高阶组件怎么用?