React <input> nested element loses focus when typing
I have:
Appcomponent with a childFiltercomponent.- The child must change the state in the parent object, which it executes via
<input onChange={handler}>. handleris apropthat is set by the parent by the parent.
So far so good.
However, whenever the a key is pressed on an input, it loses focus. I guess it was destroyed and redone.
If I raise the Filter component to the App level and disconnect it from the state in this, then everything will work as you expected, but, obviously, I would like to be able to insert components and share the state at the top level.
I assume that calling setState at this higher level will make this all happen again, but I thought this algorithm would be smart enough to avoid replacing the node in the Filter subcomponent and thus avoid blurring the focus with <input> .
What am I doing wrong / how can I fix it? Is there a better way to structure this?
Working JSBin here: http://jsbin.com/fexoyoqi/10/edit?html,js,output
var App = React.createClass({ getInitialState: function() { return { items: ["Tom", "Dick", "Harry"], filterText: '' }; }, setFilterText: function (event) { this.setState({filterText: event.target.value}); }, render: function () { var filter = React.createClass({ render: function () { return <input value={this.props.filterText} onChange={this.props.onChange}/>; } }); var rows = this.state.items .filter(function (item) { return this.state.filterText == '' ? true : item.toLowerCase().indexOf( this.state.filterText.toLowerCase()) > -1; }.bind(this)) .map(function(item) { return <li>{item}</li> }); return ( <div> Filter: <filter filterText={this.state.filterText} onChange={this.setFilterText}/> <ul> {rows} </ul> </div> ); } }); React.renderComponent(<App />, document.body); You create a new class of components inside the render function.
Part of the reactive difference algorithm looks at the components, and if it sees that you have selected a component of a different type in one place, it says: "The structure is probably significantly different, so I will not waste time making a difference with the children." It issues a node and prints a new result in the DOM.
Move var filter = React.createClass... somewhere only once, and it will work fine.