React高阶组件用法总结

高阶组件

什么是高阶组件

高阶组件就是一个 React 组件包裹着另外一个 React 组件
其中“包裹”的概念,因为它可能会有以下两种不同的含义之一:

  1. Props Proxy: HOC 对传给 WrappedComponentporps进行操作,
  2. Inheritance Inversion: HOC 继承WrappedComponent
    Props Proxy
//Props Proxy 最简实现
function ppHOC(WrappedComponent) {
    return class PP extends React.Component {
        render() {
            return <WrappedComponent {...this.props} />
        }
    }
}

使用 Props Proxy 可以做什么
• 操作 props
• 通过 Refs 访问到组件实例
• 提取 state
• 用其他元素包裹WrappedComponent

1.操作 props

function ppHOC(WrappedComponent) {
    return class PP extends React.Component {
        render() {
            const newProps = {
                id: newId
            }
            return <WrappedComponent {...this.props} {...newProps} />
        }
    }
}

2.通过 Refs 访问到组件实例

function refsHOC(WrappedComponent) {
    return class RefsHOC extends React.Component {
        proc(wrappedComponentInstance) {
            wrappedComponentInstance.method()
        }

        render() {
            const props = Object.assign({}, this.props, { ref: this.proc.bind(this) })
            return <WrappedComponent {...props} />
        }
    }
}

const refHoc = WrappedComponent => class extends Component {
    componentDidMount() {
        console.log(this.instanceComponent, 'instanceComponent');
    }
    render() {
        return (<WrappedComponent
            {...this.props}
            ref={instanceComponent => this.instanceComponent = instanceComponent}
        />);
    }
};

3.提取 state

function ppHOC(WrappedComponent) {
    return class PP extends React.Component {
        constructor(props) {
            super(props)
            this.state = {
                name: ''
            }

            this.onNameChange = this.onNameChange.bind(this)
        }
        onNameChange(event) {
            this.setState({
                name: event.target.value
            })
        }
        render() {
            const newProps = {
                name: {
                    value: this.state.name,
                    onChange: this.onNameChange
                }
            }
            return <WrappedComponent {...this.props} {...newProps} />
        }
    }
}
@ppHOC
class Example extends React.Component {
    render() {
        return <input name="name" {...this.props.name} />
    }
}

4.包裹WrappedComponent

function ppHOC(WrappedComponent) {
    return class PP extends React.Component {
        render() {
            return (
                <div style={{ display: 'block' }}>
                    <WrappedComponent {...this.props} />
                </div>
            )
        }
    }
}

Inheritance Inversion
Inheritance Inversion 最简实现

function iiHOC(WrappedComponent) {
    return class Enhancer extends WrappedComponent {
        render() {
            return super.render()
        }
    }
}

调用顺序
didmount→HOC didmount→will unmount→HOC will unmount

使用 Inheritance Inversion可以做什么

• 渲染劫持
• 操作 state

1.渲染挟持

• 有条件地渲染元素树

const MyContainer = (WrappedComponent) => class extends WrappedComponent {
    render() {
        if (this.props.loggedIn) {
            return super.render();
        } else {
            return null;
        }
    }
}

• 读取和修改由 render 输出的 React 元素树

const MyContainer = (WrappedComponent) => class extends WrappedComponent {
    render() {
        const elementsTree = super.render();
        let newProps = {};
        if (elementsTree && elementsTree.type === 'input') {
            newProps = { value: 'may the force be with you' };
        }
        const props = Object.assign({}, elementsTree.props, newProps);
        const newElementsTree = React.cloneElement(elementsTree, props, elementsTree.props.children);
        return newElementsTree;
    }
}

2.操作state

高阶组件可以读取、修改 WrappedComponent 实例中的 state,如果需要的话,也可以 增加 state。但这样做,可能会让 WrappedComponent 组件内部状态变得一团糟。

 const MyContainer = (WrappedComponent) => class extends WrappedComponent {
    render() {
        return (
            <p>
                <p>Props</p>
                <pre>{JSON.stringify(this.props)}</pre>
                <p>State</p>
                <pre>{JSON.stringify(this.state)}</pre>
                {super.render()}
            </p>);
    }
}

装饰器
高阶组件可以看做是装饰器模式(Decorator Pattern)在React的实现。即允许向一个现有的对象添加新的功能,同时又不改变其结构,属于包装模式(Wrapper Pattern)的一种
ES6中添加了一个decorator的属性,使用@符表示,可以更精简的书写。

function HOCFactoryFactory(...params) {
    // do something with params
    return function HOCFactory(WrappedComponent) {
        return class HOC extends React.Component {
            render() {
                return <WrappedComponent {...this.props} />
            }
        }
    }
}

HOCFactoryFactory(params)(WrappedComponent)
//或
@HOCFatoryFactory(params)
class WrappedComponent extends React.Component{}

该篇文章借鉴了沈老师的总结笔记,还有许多大佬的博客,如果有涉及侵权的,请联系我删除。

发布了30 篇原创文章 · 获赞 6 · 访问量 4731

猜你喜欢

转载自blog.csdn.net/EcbJS/article/details/104701206