React input onChange lag

This might seem like a trivial response but — make sure your console is closed. There is a noticeable lag in controlled components when the console is open!


This is especially an issue for big forms when a change in one input triggers the whole component re-render and that too in redux, although redux does not seem to be interfering here.

If you want your inputs to be controlled and have the same exact behaviour then you can always do like this

<input
  className="form-control"
  type="text"
  name="name"
  value={form.name}
  onBlur={onChangeHandler}
/>

This only triggers an event on blur and prevent re-render on each change. It's useful since when you click on any other button to process the data, it's guaranteed that you'll have the updated state. This will not be helpful if your logic requires instant validation/processing related to the input data.

Also, It's important I should mention that sometimes this fails to work with other components which are not native to HTML5 since they might prevent a re-render based on the value prop

Note: Please read the onBlur event here


setState by itself is not slow, it is only when your renders get very expensive that it starts causing issues.

A few things to consider are:

  • Your main component seems quite large and is being re-rendered on every keystroke so that might cause performance issues. Try breaking it down to smaller components.
  • Ensure the child-components being rendered in the render method of your main component do not get unnecessarily re-rendered. React Developer Tools or why-did-you-render can point out those unnecessary rerenders. Switching to PureComponent, stateless components or using shouldComponentUpdate can help.
  • While you can't avoid rerendering here (since your form inputs need to rerender with the new state values), by breaking into smaller components you can look to use shouldComponentUpdate to let React know if a component’s output is not affected by the current change in state or props and avoid unnecessarily rerendering.
  • If you use functional components:
    • Use useMemo to prevent recomputing expensive operations or components unless some dependency changed.
    • Use useCallback to return a memoized version of a callback so that child components that rely on reference equality don't unnecessarily rerender
    • Use React.memo if your functional component renders the same result given the same props to prevent it from unnecessarily rerendering. Use the second argument to React.memo to customize the behaviour of the memoization (similar to shouldComponentUpdate)
  • Switch to the production build to get better performance
  • Switch to uncontrolled components and let the DOM handle the input components itself (this is the "normal web form" behaviour you described). When you need to access the form's values you can use ref's to get access to the underlying DOM nodes and read the values directly off that. This should eliminate the need to call setState and therefore rerender

Tags:

Reactjs