Responsive recovery tree with HOC components (causing the input field to lose focus)

I use higher order components to decorate my components.

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

I like this template described here: Carefully respond to higher order components

However, I have a problem because the HOC calls React to recreate my component tree instead of updating the tree. This is well explained here by React Conconciliation . The HOC returns an anonymous function according to which React does not know that it actually displays the same component. This is bad for performance and causes my input field to lose focus.

How could I use HOC components without React, recreating my tree on each render() ?

Code example:

 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') ); 

See an example script (see in your browser console to see mounting and disconnecting logs from an input component each time you change input and lose focus)

+6
source share
1 answer

You do not need to create an Element in the render function. Instead, you can create it in the constructor:

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

And use it in your rendering function as follows:

  <span> <this.element value={this.state.value} onChange={this.onChange.bind(this)} /> </span> 

If necessary, you can update this.element in componentWillReceiveProps() or componentWillUpdate() .

UPDATE: fiddle

+3
source

Source: https://habr.com/ru/post/1012307/


All Articles