Jason Brill Jason Brill - 2 months ago 19
React JSX Question

React changing parent state during input onChange getting stuck

I am building a huge form which is made of atleast 50 inputs.
I have wrote a function in the form component that will save the value of the input to the form state:

PARENT FUNCTION

saveToState(details) {
const { company } = this.state;
company[details.part][details.element] = details.value;
this.setState({ company });
}


PASSING TO CHILD COMPONENT (INPUT)

<FieldInput
label="Name (as shown) *"
part="information"
element="displayName"
saveToState={this.saveToState}
/>


Here is the Input component:

import React, { Component } from 'react';
export default class FieldInput extends Component {
render() {
const { label, part, element, saveToState } = this.props;
return (
<div className="field">
<label>{label}</label>
<div className="ui input">
<input
type="text"
name={`${part}[${element}]`}
onChange={(e) => saveToState({
part,
element,
value: e.target.value
})}
/>
</div>
</div>
);
}
}


In result whenever I type something in the input It's taking it 200-300ms to really display what I wrote in the input, the state is getting updates instantly but whenever I type a character I set the new state of the parent form and update it which updates the whole component. The only way i found around it is to use
saveToState
within the parent component without passing it down. but that would require 1000's of line of code, Is there any way around this? Thanks!

Answer

There are alot of ways you can solve this problem. The easiest one and the fastest one is to use onBlur instead of onChange that way setState will happen not when you key pressing in the input but when the input loses focus.

import React, { Component } from 'react';
export default class FieldInput extends Component {
  render() {
    const { label, part, element, saveToState } = this.props;
    return (
      <div className="field">
        <label>{label}</label>
        <div className="ui input">
          <input
            type="text"
            name={`${part}[${element}]`}
            onBlur={(e) => saveToState({
              part,
              element,
              value: e.target.value
            })}
          />
        </div>
      </div>
    );
  }
}