Material UI V5 Landing Page (Taken from https://mui.com) and Formik’s landing page (Taken from https://formik.org) This will show you an alternative way (Compared to ) in which you can increase Formik’s performance when you have multiple inputs and typing into an input just becomes unbearable. The cause of this problem is as Formik re-renders on every keystroke. Matt Faircliff and Julian Rachmann CSS-In-JS and the constant re-rendering of Emotion This method isn’t necessarily exclusive to Material-UI (Although MUI is being used as an example here, and this works for both: V4.x and V5.x) and can be used with any other UI library, as the concepts are the same. Beware, this is hacky, but works in production. Here’s the that showcases you how to use it. GitHub repo The Concept - TL;DR The concept is pretty simple: We let the component handle its own internal state, and then we propagate the change to Formik with an event. We also add additional safeguards to allow for pre-filled passwords to work. In addition, when you dynamically change an attribute of the such as ,we need to have the correct way to propagate it correctly as the won’t fire. Or when you change while having . <TextField /> onBlur TextField name onBlur <Formik initialValues> enableReinitialize={true} The solution Wrap your component with the following code (Uses TypeScript): TextField PerformantTextField.tsx import { TextFieldProps, TextField } from "@mui/material"; import { useField } from "formik"; import React, { memo, useEffect, useState } from "react"; import { usePropagateRef } from "./usePropagateRef"; export type PerformantTextFieldProps = Omit<TextFieldProps, "name"> & { name: string; /** * IF true, it will use the traditional method for disabling performance */ disablePerformance?: boolean; loading?: boolean; min?: number; max?: number; }; /** * This is kind of hacky solution, but it mostly works. Your mileage may vary */ export const PerformantTextField: React.FC<PerformantTextFieldProps> = memo( (props) => { const [field, meta] = useField(props.name); const error = !!meta.error && meta.touched; /** * For performance reasons (possible due to CSS in JS issues), heavy views * affect re-renders (Formik changes state in every re-render), bringing keyboard * input to its knees. To control this, we create a setState that handles the field's inner * (otherwise you wouldn't be able to type) and then propagate the change to Formik onBlur and * onFocus. */ const [fieldValue, setFieldValue] = useState<string | number>(field.value); const { disablePerformance, loading, ...otherProps } = props; usePropagateRef({ setFieldValue, name: props.name, value: field.value, }); /** * Using this useEffect guarantees us that pre-filled forms * such as passwords work. */ useEffect(() => { if (meta.touched) { return; } if (field.value !== fieldValue) { setFieldValue(field.value); } // eslint-disable-next-line }, [field.value]); const onChange = (evt: React.ChangeEvent<HTMLInputElement>) => { setFieldValue(evt.target.value); }; const onBlur = (evt: React.FocusEvent<HTMLInputElement>) => { const val = evt.target.value || ""; window.setTimeout(() => { field.onChange({ target: { name: props.name, value: props.type === "number" ? parseInt(val, 10) : val, }, }); }, 0); }; // Will set depending on the performance props const performanceProps = disablePerformance ? { ...field, value: loading ? "Loading..." : fieldValue, } : { ...field, value: loading ? "Loading..." : fieldValue, onChange, onBlur, onFocus: onBlur, }; return ( <> <TextField {...otherProps} InputProps={{ ...((props.type === "number" && { inputProps: { min: props?.min, max: props?.max }, }) || undefined), }} error={error} helperText={meta.touched && meta.error} {...performanceProps} /> </> ); } ); We add a helper hook called usePropagateRef to allow us overcome an edge case when the attribute of the changes and data needs to be changed. name TextField usePropagateRef.ts import { useEffect, useRef } from 'react'; type UsePropagateRefProps = { setFieldValue: React.Dispatch<React.SetStateAction<any>>; name: string; value: any; }; export function usePropagateRef(props: UsePropagateRefProps) { const { name, value, setFieldValue } = props; /** * This is a special useRef that is used to propagate Formik's changes * to the component (the other way around that is done). * * This needs to be done whenever the name property changes and the content of the * component remains the same. * * An example is when you have a dynamic view that changes the TextField's name attribute. * If we don't do this, the useBlur hook will overwrite the value that you left before you * changed the TextField's value. * */ const flagRef = useRef(true); useEffect(() => { if (flagRef.current) { flagRef.current = false; return; } setFieldValue(value); // eslint-disable-next-line }, [name]); } This should set you to a much more smooth experience while using the <TextField /> GitHub Repo Check it out here: https://github.com/superjose/increase-formik-performance-react The files to be checked can be found here: src/components/Fields/Form/PerformantTextField/