Stas Kurilin Stas Kurilin - 4 months ago 63
React JSX Question

Simplest high order components and material-ui

When I'm using TextField directly from my component it works perfectly fine (case 1), however when I'm wrapping it inside function (case 2) from props it loosing focus after one each change.

import TextField from 'material-ui/TextField';

var Comp = React.createClass({
getInitialState: function () {
return {description: ""};
},
descriptionChanged: function (e) {
this.setState({description: e.target.value});
},
render: function () {
var self = this;
var T2 = function (props) {
return <TextField hintText="Desc2"
value={self.state.description}
onChange={self.descriptionChanged}/>;
};
return <div>
1 <TextField hintText="Desc1"
value={self.state.description}
onChange={self.descriptionChanged}
/>
2 <T2/>
</div>

}
});


jsfiddle

Why it's happening and how I can fix it?

Answer

This is because you are making a new function (and thus a new high order component) each time you render. React will think this is a completely different type of component and will destroy the old DOM to make the new.

In this version we make the high order component once when your component instance is created.

import TextField from 'material-ui/TextField';

var Comp = React.createClass({
    getInitialState: function () {
        return {description: ""};
    },
    componentWillMount() {
        // create HOC once for this instance
        var self = this;
        this.T2 = function (props) {
            return <TextField hintText="Desc2"
                              value={self.state.description}
                              onChange={self.descriptionChanged}/>;
        };
    },
    descriptionChanged: function (e) {
        this.setState({description: e.target.value});
    },
    render: function () {
        var self = this;
        var T2 = this.T2;
        return <div>
            1 <TextField hintText="Desc1"
                       value={self.state.description}
                       onChange={self.descriptionChanged}
            />
            2 <T2/>
        </div>

    }
});