So I have a big component that would be my form:
<form>
<FirstComponent value={this.state.firstValue}/>
<SecondComponent value={this.state.secondValue}/>
{more components here}
<input type="submit" ... />
</form>
This form component is listening for a store that updates its values using firstAction
, secondAction
, etc.
Note: Component updates its state based on store.getState() that returns {firstValue: something, secondValue: something, etc}
So let's say my FirstComponent
is an input:
<input type="text" value={this.props.value}
onChange={(e)=>this.props.firstAction(e.target.value)}
</input>
Ok, so the onChange
fires the prop firstAction
which is actually the Flux action that will update my store and make the form to re-render. I have two good things here, when user submits the form, I can check the value of FirstComponent in my store and I also control all my state from the parent component.
However, this onChange
callback will call an action every time the user types one character (so it can produce a lot of calls therefore re-renders) <-- can this provoke serious performance issues?
Instead, I could use refs and when the user press the submit button, get this.refs.myFirstComponent.state
... and I will have the value too (that would be Uncontrolled Component?) But this does not sound like a recommendation from the community.
So my question is, is the first approach I described above a good way to go? How can I optimize it? So a re-render that should only affect FirstComponent does not make SecondComponent and so on to re-render? Is shouldComponentUpdate
the only way to go here?
Edit 1:
With the first approach I am facing a problem... I have an e2e test using WebdriverIO adding a value into the text field: http://webdriver.io/api/action/setValue.html
I don't know why but if I am trying to add the word "Testing" into the input, webdriver will only add the last letter. This problem is gone if not using state/store at all. However, if I have the state internally to my FirstComponent
, something like:
<input type="text" value={this.state.value}
onChange={(e)=>this.setState({firstValue: e.target.value})}
onBlur={()=>this.props.callback(this.state.firstValue)}
</input>
In this case, component seems to react faster while typing (only renders itself), and then, when user removes focus it updates the store. I have to say, I don't like this approach because it doesn't follow the pattern of take your state up (and I feel I am duplicating the state) BUT it seems to work faster and more important: My e2e test works. Any more ideas?