Formik is a comprehensive React form library that simplifies building, validating, and handling forms in React applications. It provides a declarative API for managing form state, validation, and error handling through render props, hooks, and higher-order components. The library offers seamless integration with popular validation libraries like Yup, supports both synchronous and asynchronous validation, and handles complex form scenarios including nested objects, arrays, and dynamic fields.
npm install formikimport { Formik, Field, Form, useFormik } from "formik";For CommonJS:
const { Formik, Field, Form, useFormik } = require("formik");Additional imports for advanced functionality:
import {
FieldArray,
ErrorMessage,
FastField,
withFormik,
useFormikContext,
FormikProvider
} from "formik";import { Formik, Field, Form, ErrorMessage } from "formik";
import * as Yup from "yup";
interface FormValues {
email: string;
password: string;
}
const LoginSchema = Yup.object().shape({
email: Yup.string().email('Invalid email').required('Required'),
password: Yup.string().min(6, 'Too Short!').required('Required'),
});
const LoginForm = () => (
<Formik
initialValues={{ email: '', password: '' }}
validationSchema={LoginSchema}
onSubmit={(values, { setSubmitting }) => {
console.log(values);
setSubmitting(false);
}}
>
<Form>
<Field name="email" type="email" placeholder="Email" />
<ErrorMessage name="email" component="div" />
<Field name="password" type="password" placeholder="Password" />
<ErrorMessage name="password" component="div" />
<button type="submit">Submit</button>
</Form>
</Formik>
);Alternative hook-based approach:
import { useFormik } from "formik";
const LoginForm = () => {
const formik = useFormik({
initialValues: { email: '', password: '' },
validationSchema: LoginSchema,
onSubmit: values => {
console.log(values);
},
});
return (
<form onSubmit={formik.handleSubmit}>
<input
id="email"
name="email"
type="email"
onChange={formik.handleChange}
onBlur={formik.handleBlur}
value={formik.values.email}
/>
{formik.touched.email && formik.errors.email ? (
<div>{formik.errors.email}</div>
) : null}
<button type="submit">Submit</button>
</form>
);
};Formik is built around several key architectural patterns:
<Formik>, <Field>, and <Form> components provide declarative form managementuseFormik and useField hooks for functional component integrationEssential components for building forms with declarative syntax and automatic state management.
function Formik<Values = any>(props: FormikConfig<Values>): JSX.Element;
interface FormikConfig<Values> {
initialValues: Values;
onSubmit: (values: Values, formikHelpers: FormikHelpers<Values>) => void | Promise<any>;
validationSchema?: any;
validate?: (values: Values) => void | object | Promise<FormikErrors<Values>>;
validateOnChange?: boolean;
validateOnBlur?: boolean;
validateOnMount?: boolean;
isInitialValid?: boolean | ((props: any) => boolean);
enableReinitialize?: boolean;
children?: ((props: FormikProps<Values>) => React.ReactNode) | React.ReactNode;
component?: React.ComponentType<FormikProps<Values>>;
render?: (props: FormikProps<Values>) => React.ReactNode;
innerRef?: React.Ref<FormikProps<Values>>;
initialStatus?: any;
initialErrors?: FormikErrors<Values>;
initialTouched?: FormikTouched<Values>;
onReset?: (values: Values, formikHelpers: FormikHelpers<Values>) => void;
}Hook-based form state management for functional components, providing complete form control without component wrappers.
function useFormik<Values extends FormikValues = FormikValues>(
config: FormikConfig<Values>
): FormikProps<Values>;
interface FormikProps<Values> {
values: Values;
errors: FormikErrors<Values>;
touched: FormikTouched<Values>;
isSubmitting: boolean;
isValidating: boolean;
status?: any;
submitCount: number;
dirty: boolean;
isValid: boolean;
initialValues: Values;
handleSubmit: (e?: React.FormEvent<HTMLFormElement>) => void;
handleReset: (e?: React.SyntheticEvent<any>) => void;
handleBlur: (e: React.FocusEvent<any>) => void;
handleChange: (e: React.ChangeEvent<any>) => void;
setFieldValue: (field: string, value: any, shouldValidate?: boolean) => Promise<void | FormikErrors<Values>>;
setFieldError: (field: string, message: string | undefined) => void;
setFieldTouched: (field: string, isTouched?: boolean, shouldValidate?: boolean) => Promise<void | FormikErrors<Values>>;
validateForm: (values?: any) => Promise<FormikErrors<Values>>;
validateField: (field: string) => Promise<void> | Promise<string | undefined>;
resetForm: (nextState?: Partial<FormikState<Values>>) => void;
submitForm: () => Promise<void>;
}Components and utilities for managing dynamic arrays of form fields with helper methods for manipulation.
function FieldArray(props: FieldArrayConfig): JSX.Element;
interface FieldArrayConfig {
name: string;
children?: (props: FieldArrayRenderProps) => React.ReactNode;
component?: React.ComponentType<FieldArrayRenderProps>;
render?: (props: FieldArrayRenderProps) => React.ReactNode;
}
interface ArrayHelpers<T = any> {
push: (obj: T) => void;
pop: () => T | undefined;
remove: (index: number) => T | undefined;
insert: (index: number, value: T) => void;
unshift: (value: T) => number;
move: (from: number, to: number) => void;
swap: (indexA: number, indexB: number) => void;
replace: (index: number, value: T) => void;
}Components and patterns for displaying validation errors with flexible rendering options.
function ErrorMessage(props: ErrorMessageProps): JSX.Element | null;
interface ErrorMessageProps {
name: string;
component?: React.ComponentType<any> | string;
children?: ((error: string) => React.ReactNode);
render?: (error: string) => React.ReactNode;
className?: string;
}React Context providers and higher-order components for advanced integration patterns and legacy component support.
function useFormikContext<Values>(): FormikContextType<Values>;
function withFormik<OuterProps, Values, Payload = Values>(
config: WithFormikConfig<OuterProps, Values, Payload>
): ComponentDecorator<OuterProps, OuterProps & InjectedFormikProps<OuterProps, Values>>;
const FormikProvider: React.Provider<FormikContextType<any>>;
const FormikConsumer: React.Consumer<FormikContextType<any>>;interface FormikValues {
[field: string]: any;
}
type FormikErrors<Values> = {
[K in keyof Values]?: Values[K] extends any[]
? Values[K][number] extends object
? FormikErrors<Values[K][number]>[] | string | string[]
: string | string[]
: Values[K] extends object
? FormikErrors<Values[K]>
: string;
};
type FormikTouched<Values> = {
[K in keyof Values]?: Values[K] extends any[]
? Values[K][number] extends object
? FormikTouched<Values[K][number]>[]
: boolean
: Values[K] extends object
? FormikTouched<Values[K]>
: boolean;
};
interface FormikState<Values> {
values: Values;
errors: FormikErrors<Values>;
touched: FormikTouched<Values>;
isSubmitting: boolean;
isValidating: boolean;
status?: any;
submitCount: number;
}
interface FormikComputedProps<Values> {
readonly dirty: boolean;
readonly isValid: boolean;
readonly initialValues: Values;
readonly initialErrors: FormikErrors<Values>;
readonly initialTouched: FormikTouched<Values>;
readonly initialStatus?: any;
}
interface FormikHelpers<Values> {
setStatus: (status?: any) => void;
setErrors: (errors: FormikErrors<Values>) => void;
setSubmitting: (isSubmitting: boolean) => void;
setTouched: (touched: FormikTouched<Values>, shouldValidate?: boolean) => Promise<void | FormikErrors<Values>>;
setValues: (values: React.SetStateAction<Values>, shouldValidate?: boolean) => Promise<void | FormikErrors<Values>>;
setFieldValue: (field: string, value: any, shouldValidate?: boolean) => Promise<void | FormikErrors<Values>>;
setFieldError: (field: string, message: string | undefined) => void;
setFieldTouched: (field: string, isTouched?: boolean, shouldValidate?: boolean) => Promise<void | FormikErrors<Values>>;
validateForm: (values?: any) => Promise<FormikErrors<Values>>;
validateField: (field: string) => Promise<void> | Promise<string | undefined>;
resetForm: (nextState?: Partial<FormikState<Values>>) => void;
submitForm: () => Promise<void>;
setFormikState: (f: FormikState<Values> | ((prevState: FormikState<Values>) => FormikState<Values>), cb?: () => void) => void;
}
type FieldValidator = (value: any) => string | void | Promise<string | void>;
interface FieldConfig<V = any> {
name: string;
validate?: FieldValidator;
[key: string]: any;
}
interface SharedRenderProps<T> {
component?: keyof JSX.IntrinsicElements | React.ComponentType<T | void>;
render?: (props: T) => React.ReactNode;
children?: (props: T) => React.ReactNode;
}
type GenericFieldHTMLAttributes =
| JSX.IntrinsicElements['input']
| JSX.IntrinsicElements['select']
| JSX.IntrinsicElements['textarea'];
interface FormikRegistration {
registerField: (name: string, fns: { validate?: FieldValidator }) => void;
unregisterField: (name: string) => void;
}
interface FieldMetaProps<Value> {
value: Value;
error?: string;
touched: boolean;
initialValue?: Value;
initialTouched: boolean;
initialError?: string;
}
interface FieldHelperProps<Value> {
setValue: (value: Value, shouldValidate?: boolean) => Promise<void | FormikErrors<Value>>;
setTouched: (value: boolean, shouldValidate?: boolean) => Promise<void | FormikErrors<Value>>;
setError: (value: string | undefined) => void;
}
interface FieldInputProps<Value> {
value: Value;
name: string;
multiple?: boolean;
checked?: boolean;
onChange: (e: React.ChangeEvent<any>) => void;
onBlur: (e: React.FocusEvent<any>) => void;
}