使用HOC组件反应重建树(导致输入字段焦点丢失)

Ste*_*ren 7 reactjs

我正在使用高阶组件来装饰我的组件.

const HOC = (WrappedComponent) => (props) => {
    return (
        <span>
            <p>HOC Comp</p>
            <WrappedComponent {...props}/>
        </span>
    )
}
Run Code Online (Sandbox Code Playgroud)

我喜欢这里解释的这种模式:深入反应高阶组件

但是我有一个问题,因为HOC导致React重新创建我的组件树而不是更新树.这里很好地解释了React Reconciliation.HOC返回一个匿名函数,React不知道它实际上是在渲染相同的组件.这对性能不利,使我的输入字段失去焦点.

如果没有React重新创建我的树,我怎么能使用HOC组件render()呢?

示例代码:

class Input extends React.Component {
    componentWillMount() {
        console.log('input component will mount');
    }

    componentWillUnmount() {
        console.log('input component will unmount');
    }

    render() {
        return (
            <span>
                <input value={this.props.value} onChange={this.props.onChange}/>
            </span>
        );
    }
}

const HOC = (WrappedComponent) => {
    const Help = (props) => {
        return (
            <span>
                <WrappedComponent {...props}/>
                <p>{props.help}</p>
            </span>
        )
    };

    return Help;
}

class MyComponent extends React.Component {
    constructor (props) {
        super(props);
        this.state = {value : 'start value'}
    }

    onChange(event) {
        this.setState({value : event.target.value});
    }

    render() {
        const Element = HOC(Input);
        return (
            <span>
                <Element
                    value={this.state.value}
                    onChange={this.onChange.bind(this)}
                />
            </span>
        )
    }
}

ReactDOM.render(
    <MyComponent />,
    document.getElementById('container')
);
Run Code Online (Sandbox Code Playgroud)

请参阅小提琴示例(请在浏览器的控制台中查看,每次更改输入时都会看到输入组件中的挂载和卸载日志并失去焦点)

Sim*_*olt 6

您不必Element在渲染功能中创建.相反,您可以在构造函数中创建它:

class MyComponent extends React.Component {
    constructor (props) {
        super(props);
        this.state = {value : 'start value'};
        this.element = HOC(Input);
    }
...
Run Code Online (Sandbox Code Playgroud)

并在你的渲染函数中使用它,如下所示:

        <span>
            <this.element
                value={this.state.value}
                onChange={this.onChange.bind(this)}
            />
        </span>
Run Code Online (Sandbox Code Playgroud)

如果需要的话您可以更新this.elementcomponentWillReceiveProps()componentWillUpdate().

更新:小提琴