简单理解react的高阶组件其实就是定义一个函数。这个函数接收一个组件为参数,返回一个进行过封装,拓展的新的组件。
现在常用到的两种实现方式
1.属性代理
封装或者扩展传入的组件。为布局或者添加功能将传入组件进行包裹
function HOC(WrappedComponent) {
return class PP extends React.Component {
render() {
return (
<div>
<WrappedComponent {...this.props}/>
<Modal/>
</div>
)
}
}
}
添加新的props
function HOC(WrappedComponent) {
return class PP extends React.Component {
render() {
const newProps = {
name: 'zhangsan'
}
return <WrappedComponent {...this.props} {...newProps}/>
}
}
}
2.反向继承
高阶组件继承与传入的组件
HOC继承了WrappedComponent,意味着可以访问到WrappedComponent的state,props,生命周期和render方法。如果在HOC中定义了与WrappedComponent同名方法,将会发生覆盖,就必须手动通过super进行调用。通过完全操作WrappedComponent的render方法返回的元素树,可以真正实现渲染劫持。这种思想具有较强的入侵性。
function ppHOC(WrappedComponent) {
return class ExampleEnhance extends WrappedComponent {
...
componentDidMount() {
super.componentDidMount();
}
componentWillUnmount() {
super.componentWillUnmount();
}
render() {
...
return super.render();
}
}
}
HOC中ref的使用(react.forwardRef)
当使用HOC后应为组件上边还有一层,ref取到的其实是hoc的实例,并不能拿到我们想要的。
react 16.3之前的做法是在hoc中定义this.childRef = React.createRef();
const HOC = function(WrappedComponent) {
return class PP extends React.Component {
constructor(props) {
super(props);
this.child = React.createRef();
}
render() {
return <WrappedComponent ref={this.child} {...this.props}/>
}
}
}
@HOC
const ChildComponent = () => {
return <div>hellow word</div>
}
class Com extends React.Component {
constructor(props) {
super(props);
this.child = React.createRef();
}
componentDidMount() {
console.log(this.child.current.child);
}
render() {
return <ChildComponent ref={this.child} {...this.props}/>
}
}
react 16.3之后新增了React.forwardRef可以使ref直接透传到组件上,而不是HOC
// 使用forwardRef给纯函数组件包裹后使其拥有ref
const ChildComponent = React.forwardRef((props, ref) => (
<button ref={ref}>
{this.props.children}
</button>
)})
const ref = React.createRef();
<ChildComponent>chick me!</ChildComponent>
// HOC透传ref
function (Component) {
class LogProps extends React.Component {
componentDidUpdate(prevProps) {
console.log('old props', prevProps);
console.log('new props', this.props);
}
render() {
const {forwardRef, ...rest} = this.props;
// Assign the custom prop 'forwardedRef' as a ref
// 将自定义props “forwardedRef” 保存到ref上
return <Component ref={forwardedRef} {...rest} />
}
}
// Note the second param 'ref' provided by React.forwardRef.
// 第二个参数由forwardRef提供的
// We can pass it along to LogProps as regular prop. e.g. 'forwardedRef'
// 将forwardedRef传给LogProps组件
// And it can then be attached to Component.
return React.forwardRef((props, ref) => {
return <LogProps {...props} forwardedRef={ref} />
})
}
以上!