Concern over onChange of several components
See original GitHub issueI have been using material UI for over 2 years now and I have come to realize a possible design flaw to be discussed. Many of our forms are inline inside of one main render class with many input boxes and other complicated components and sometimes with <TextField/> components, things sometimes can render slow because our main form component has to re-render on each keypress from a user. This is because our onChange event is a typically a setState to set the state of the bound value to pass as props to each component we bind to.
- This is a v1.x issue (v0.x is no longer maintained).
- I have searched the issues of this repository and believe that this is not a duplicate.
Expected Behavior
I wanted to discuss some kind of possible change to allow the values to change inside of the component rather than making the caller pass value as a prop. By making the caller setState and set value into the parent state and passing it along as props, you have to re-render all sibling components who might hold state for other nodes just to get the value to be set according to what someone types.
Here is an example component which takes the value within the component rather than always relying on props passed to set the value, where its appropriate in this case to just set the value of the parent onBlur where a render could occur after all has been typed.
class Input extends BaseComponent {
constructor(props, context) {
super(props, context);
this.state = {
value: props.value,
style: props.style
};
}
render() {
return <input style={this.state.style} key="input-label2" maxLength={this.props.maxLength} type='text' className='form-control' value={this.state.value}
onChange={(e) => {
this.setState({value: e.target.value});
}}
onBlur={() => {
this.props.onBlur(this.state.value);
}}/>
}
}
I mostly just wanted opinions on this topic and maybe I can send a pull request of (at least for input boxes) allowing a version which sets the state within the component internally so that the parent setState doesnt re-render the entire (slow form if there are a lot of nodes).
My opinion is that its not an ideal practice to only rely on props to setState and not keep the state of values internal to your component. I have formed this opinion after years of seeing a slow typing response where my entire forms get progressively slower because material UI only relies on props passed to set the value. Each developer has to abstract your input boxes to their own component setting state to get it to work more efficiently to not render the entire “sibling form component”
Thank you for your time and thoughts on this matter. Maybe I am just doing something wrong and I am open to feedback of something I might be doing wrong.
Cheers!
Issue Analytics
- State:
- Created 5 years ago
- Comments:5 (2 by maintainers)
Top GitHub Comments
For anyone in the same boat as our team where sometimes forms render slow/sluggish for TextField component and you come across this thread, here is an example abstraction which is stateful and isolated to just rendering that node and not all the nodes in your form.
https://gist.github.com/davidrenne/28e123e27417f3326aee18363f69bc77
@davidrenne This problem highlights the limitation of the brute-force approach. Updating the whole form component at each keystroke doesn’t scale. But you are not the first one to face it. People have been building abstractions since the beginning of React to address it. I would encourage you to pick one of the popular React form library (react-final-form, react-redux, formik). You won’t have this problem. They provide abstractions to keep each form field controlled and performant by scoping the updates.
It’s not something we will fix at the Material-UI level. As @mbrookes stated, we have designed the current situation on purpose, we are well aware of the tradeoff and happy with it.