---
name: formik
description: Manages React form state with Formik using validation, field arrays, and form context. Use when building complex forms in React, handling form submission, or integrating with Yup validation.
---
# Formik
Form state management library for React with built-in validation, submission handling, and field management.
## Quick Start
```bash
npm install formik yup
```
```tsx
import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';
const schema = Yup.object({
email: Yup.string().email('Invalid email').required('Required'),
password: Yup.string().min(8, 'Too short').required('Required'),
});
function LoginForm() {
return (
{
console.log(values);
setSubmitting(false);
}}
>
{({ isSubmitting }) => (
)}
);
}
```
## useFormik Hook
```tsx
import { useFormik } from 'formik';
function Form() {
const formik = useFormik({
initialValues: {
email: '',
password: '',
},
validationSchema: schema,
onSubmit: (values) => {
console.log(values);
},
});
return (
);
}
```
## Field Component
### Basic Fields
```tsx
```
### With Custom Component
```tsx
{({ field, meta }) => (
{meta.touched && meta.error && {meta.error}}
)}
```
### Custom Input Component
```tsx
const TextInput = ({ label, ...props }) => {
const [field, meta] = useField(props);
return (
{meta.touched && meta.error &&
{meta.error}
}
);
};
// Usage
```
## Form Component
```tsx
```
Or with render prop:
```tsx
{(formikProps) => (
)}
```
## Validation
### With Yup
```tsx
import * as Yup from 'yup';
const validationSchema = Yup.object({
firstName: Yup.string()
.max(15, 'Must be 15 characters or less')
.required('Required'),
lastName: Yup.string()
.max(20, 'Must be 20 characters or less')
.required('Required'),
email: Yup.string()
.email('Invalid email')
.required('Required'),
});
```
### Custom Validate Function
```tsx
{
const errors = {};
if (!values.email) {
errors.email = 'Required';
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)) {
errors.email = 'Invalid email';
}
return errors;
}}
...
/>
```
### Field-Level Validation
```tsx
const validateUsername = async (value) => {
if (!value) return 'Required';
const taken = await checkUsername(value);
if (taken) return 'Username taken';
};
```
## Field Arrays
```tsx
import { FieldArray } from 'formik';
{({ values }) => (
)}
```
### Array of Objects
```tsx
{({ values }) => (
{({ push, remove }) => (
<>
{values.contacts.map((contact, index) => (
))}
>
)}
)}
```
## Formik Context
### useFormikContext
```tsx
import { useFormikContext } from 'formik';
function SubmitButton() {
const { isSubmitting, isValid } = useFormikContext();
return (
);
}
```
### Accessing Form State
```tsx
function FormDebug() {
const { values, errors, touched, isValid, dirty } = useFormikContext();
return (
{JSON.stringify({ values, errors, touched, isValid, dirty }, null, 2)}
);
}
```
## Form State
### Formik Props
```tsx
{({
// Values
values, // Form values
initialValues, // Initial values
errors, // Validation errors
touched, // Touched fields
// Status
isSubmitting, // Submit in progress
isValid, // No validation errors
isValidating, // Validation in progress
dirty, // Values changed from initial
// Handlers
handleSubmit, // Form submit handler
handleChange, // Input change handler
handleBlur, // Input blur handler
handleReset, // Reset form
// Helpers
setFieldValue, // Set specific field
setFieldTouched, // Mark field as touched
setFieldError, // Set field error
setValues, // Set all values
setErrors, // Set all errors
setTouched, // Set all touched
setStatus, // Set form status
setSubmitting, // Set submitting state
resetForm, // Reset to initial
validateForm, // Trigger validation
validateField, // Validate specific field
// Getters
getFieldProps, // Get field props helper
getFieldMeta, // Get field meta (error, touched)
getFieldHelpers, // Get field helpers
}) => (
)}
```
## Submission
### Basic Submit
```tsx
{
submitToServer(values).then(() => {
setSubmitting(false);
});
}}
...
/>
```
### Async Submit
```tsx
{
try {
await api.submit(values);
resetForm();
setStatus({ success: true });
} catch (error) {
setStatus({ error: error.message });
} finally {
setSubmitting(false);
}
}}
...
/>
```
### With Server Errors
```tsx
{
try {
await api.submit(values);
} catch (error) {
if (error.validationErrors) {
setErrors(error.validationErrors);
}
}
}}
...
/>
```
## Enable/Disable Reinitialize
```tsx
```
## TypeScript
```tsx
interface FormValues {
email: string;
password: string;
}
const initialValues: FormValues = {
email: '',
password: '',
};
initialValues={initialValues}
onSubmit={(values: FormValues) => {
console.log(values.email);
}}
...
/>
```
### Typed Custom Field
```tsx
import { useField, FieldHookConfig } from 'formik';
interface TextInputProps extends FieldHookConfig {
label: string;
}
const TextInput: React.FC = ({ label, ...props }) => {
const [field, meta] = useField(props);
return (
{meta.touched && meta.error &&
{meta.error}
}
);
};
```
See [references/patterns.md](references/patterns.md) for advanced patterns and recipes.