Custom react dropdown component re-rendering on every user input

2.4k views Asked by At

I'm having a bit of trouble with controlling the amount of re rendering done by React. Say I've got this user input right here:

handleFirstNameChange: function(e) {
    this.setState({ firstName: e.target.value, userTyping: true });
},
render: function(){
<RB.Input value={this.state.firstName} onChange={this.handleFirstNameChange} name=""
                    type="text" label="First name" placeholder="First name.."/>
}

And this custom dropdown component:

<SearchDropdown title="Role" options={this.props.currentUser.roles} 
                            selectedOptions={this.props.currentUser.selectedRoles} />

Every single time the user inputs a letter, the dropdown will re render every single option, even though (as it seems) the components have nothing common to each other. I've been trying to manage this by including a "userIsTyping" boolean as a prop to the dropdown component and checking it in ComponentShouldUpdate but it's becoming more of a problem now that I've got nested components. I'm still in my early stages of using React so I'm pretty sure there's something obvious here that I'm missing.

3

There are 3 answers

1
Colin Ramsay On BEST ANSWER

With React, onChange fires every time a key is pressed. In your code, this will in turn cause a call to setState via the handleFirstNameChange handler, and that will cause a re-render.

Two options:

  1. Don't worry about it. Re-rendering isn't necessarily going to cause you any problems, and if there's no performance issue then you could just ignore this. Your component is fairly simple if I were in your shoes I'd probably just forget about it :)
  2. Don't use onChange, use onBlur and then your handler will only fire when the field loses focus.

You can read more about the behaviour of onChange in React in the documentation:

https://facebook.github.io/react/docs/forms.html#interactive-props

0
Michael Parker On

React was designed to intelligently compute the most efficient DOM manipulations that would be required to get the desired output, so it isn't really a problem that your component is being re-rendered so often.

It looks like you're using onChange to update your component's state whenever your input has a different value. Might I recommend the LinkedStateMixin? This way, you could force a particular state to always be consistent with some value in an input.

render: function(){
<RB.Input valueLink={this.linkState.firstName} name=""
                    type="text" label="First name" placeholder="First name.."/>
}

In that code above (assuming that RB.Input behaves the same way as a typical input), your component's firstName state will always be equivalent to whatever value contained within your input.

0
cjm On

You can manage re-render conditions for a React component by adding the lifecycle method shouldComponentUpdate to your class.

I'm not sure what conditions would actually require a re-render of the dropdown in your application, but you can specify those conditions for react like this:

var SearchDropdown = React.createClass({

    // ... (your existing code)

    shouldComponentUpdate: function(nextProps, nextState) {
        // Do a boolean compare; re-render only if this returns true
        return this.props.options.somethingToCheck !== nextProps.options.somethingToCheck;
    }
});

Docs: https://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate