6.1.2 继承方式的高阶组件
您可以在百度里搜索“深入浅出React和Redux 艾草文学(www.321553.xyz)”查找最新章节!
6.1.2 继承方式的高阶组件
继承方式的高阶组件采用继承关系关联作为参数的组件和返回的组件,假如传入的组件参数是WrappedComponent,那么返回的组件就直接继承自WrappedComponent。
我们用继承方式重新实现一遍removeUserProp这个高阶组件,代码如下:
function removeUserProp(WrappedComponent) {
return class NewComponent extends WrappedComponent {
render() {
const {user, ...otherProps} = this.props;
this.props = otherProps;
return super.render();
}
};
}
代理方式和继承方式最大的区别,是使用被包裹组件的方式。
在代理方式下,render函数中的使用被包裹组件是通过JSX代码:
return
在继承方式下,render函数中渲染被包裹组件的代码如下:
return super.render();
因为我们创造的新的组件继承自传入的WrappedComponent,所以直接调用super.render就能够得到渲染出来的元素。
需要注意,在代理方式下WrappedComponent经历了一个完整的生命周期,但在继承方式下super.render只是一个生命周期中的一个函数而已;在代理方式下产生的新组件和参数组件是两个不同的组件,一次渲染,两个组件都要经历各自的生命周期,在继承方式下两者合二为一,只有一个生命周期。
在上面的例子中我们直接修改了this.props,这实在不是一个好做法,实际上,这样操作可能产生不可预料的结果。
继承方式的高阶组件可以应用于下列场景:
·操纵prop;
·操纵生命周期函数。
1.操纵Props
继承方式的高阶组件也可以操纵props,除了上面不安全的直接修改this.props方法,还可以利用React.cloneElement让组件重新绘制:
const modifyPropsHOC = (WrappedComponent) => {
return class NewComponent extends WrappedComponent {
render() {
const elements = super.render();
const newStyle = {
color: (elements && elements.type === 'div') ? 'red' : 'green'
}
const newProps = {...this.props, style: newStyle};
return React.cloneElement(elements, newProps,lements.props.children);
}
};
};
上面的高阶组件实现的功能是首先检查参数组件的render函数返回结果,如果顶层元素是一个div,就将其增加一个color为red的style属性,否则增加color为green的style属性。最后,我们用React.cloneElement来传入新的props,让这些产生的组件重新渲染一遍。
虽然这样可行,但是过程实在非常复杂,唯一用得上的场景就是高阶组件需要根据参数组件WrappedComponent渲染结果来决定如何修改props。否则,实在没有必要用继承方式来实现这样的高阶组件,使用代理方式实现操纵prop的功能更加清晰。
2.操纵生命周期函数
因为继承方式的高阶函数返回的新组件继承了参数组件,所以可以重新定义任何一个React组件的生命周期函数。
这是继承方式高阶函数特用的场景,代理方式无法修改传入组件的生命周期函数,所以不具备这个功能。
例如,我们可以定义一个高阶组件,让参数组件只有在用户登录时才显示,代码如下:
const onlyForLoggedinHOC = (WrappedComponent) => {
return class NewComponent extends WrappedComponent {
render() {
if (this.props.loggedIn) {
return super.render();
} else {
return null;
}
}
}
}
又例如,我们可以重新定义shouldComponentUpdate函数,只要prop中的useCache不为逻辑false就不做重新渲染的动作,代码如下:
const cacheHOC = (WrappedComponent) => {
return class NewComponent extends WrappedComponent {
shouldComponentUpdate(nextProps, nextState) {
return !nextProps.useCache;
}
}
}
从上面例子的比较可以看出来,各方面看来代理方式都要优于继承方式。
业界有一句老话:“优先考虑组合,然后才考虑继承。”(Composition over Inheritance)。前人诚不欺我,我们应该尽量使用代理方式来构建高阶组件。 深入浅出React和Redux