React <input> nested element loses focus when typing

I have:

  • App component with a child Filter component.
  • The child must change the state in the parent object, which it executes via <input onChange={handler}> .
  • handler is a prop that 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); 
+7
reactjs
source share
1 answer

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.

+14
source share

All Articles