我正在使用高阶组件来装饰我的组件。
const HOC = (WrappedComponent) => (props) => {
return (
<span>
<p>HOC Comp</p>
<WrappedComponent {...props}/>
</span>
)
}
我确实喜欢这里解释的这种模式:React Higher Order Components in depth
但是我有一个问题,因为 HOC 导致 React 重新创建我的组件树而不是更新树。这在这里得到了很好的解释React Reconciliation 。 HOC 返回一个匿名函数,React 不知道它实际上正在渲染相同的组件。这对性能不利,并使我的输入字段失去焦点。
如何使用 HOC 组件而不用 React 在每个 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')
);
参见Fiddle example (每次更改输入并失去焦点时,请在浏览器的控制台中查看输入组件的安装和卸载日志)
最佳答案
您不必在渲染函数中创建Element
。相反,您可以在构造函数中创建它:
class MyComponent extends React.Component {
constructor (props) {
super(props);
this.state = {value : 'start value'};
this.element = HOC(Input);
}
...
并在渲染函数中使用它,如下所示:
<span>
<this.element
value={this.state.value}
onChange={this.onChange.bind(this)}
/>
</span>
如果需要,您可以在 componentWillReceiveProps()
或 componentWillUpdate()
中更新 this.element
。
更新:fiddle
关于reactjs - 使用 HOC 组件 React 重建树(导致输入字段焦点丢失),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40590515/