Fix React Hook Form Flickering [Solved]

Immediate Fix

The most common cause of flickering in React Hook Form is the default validation mode. By default, many developers trigger validation on every keystroke, causing the UI to jump as error messages toggle.

To stop the flickering instantly, switch your useForm configuration from onChange to onTouched or onBlur. This prevents the state from updating and re-rendering the layout until the user moves to the next field.

const { register, handleSubmit } = useForm({
  mode: 'onTouched',
  reValidateMode: 'onBlur',
  shouldUnregister: false
});
Mode Effect Flicker Risk
onChange Validates on every key press High
onBlur Validates when leaving input Low
onTouched Validates after first interaction Medium

Technical Explanation

Flickering occurs during the React reconciliation process. When React Hook Form updates its internal state to reflect a validation error, it triggers a re-render of the component tree.

If your form layout depends on conditional rendering—such as showing an error message that shifts other elements down—the rapid mounting and unmounting of these elements creates a visible “stutter” or flicker.

Another technical cause is the use of asynchronous defaultValues. If you are fetching data and updating the form using reset() inside a useEffect, the form might render once with empty values and then a second time with the fetched data, causing a flash of empty content.

A diagram showing how to prevent screen flickering in React Hook Form.

Alternative Methods

1. Use the Controller Component

For complex UI libraries like Material UI or Ant Design, wrap your inputs in the Controller component. This provides a more stable bridge between the external input state and React Hook Form, reducing unnecessary parent re-renders.

<Controller
  name="firstName"
  control={control}
  render={({ field }) => <Input {...field} />}
/>

2. Persistent Error Layouts

Instead of conditionally rendering error messages, keep the error container in the DOM with a fixed height. Use CSS visibility or opacity to show the text. This prevents the layout from shifting when the error appears.

/* CSS to prevent layout shift */
.error-message {
  min-height: 20px;
  visibility: hidden;
}
.error-message.visible {
  visibility: visible;
}

3. Memoize Form Inputs

If your form is large, use React.memo on individual input components. This ensures that only the input currently being typed in re-renders, while the rest of the form remains static, eliminating the global screen flicker.