KS
Killer-Skills

formik — how to use formik how to use formik, formik vs react-hook-form, formik install, formik setup guide, what is formik, formik alternative, formik validation, formik react forms, formik tutorial

v1.0
GitHub

About this Skill

Perfect for Frontend Agents building complex React applications needing efficient form state management and validation. formik is an open-source form library for React, used for building, validating, and managing forms in React applications.

Features

Handles form validation with or without Yup
Manages form state, field values, and errors
Supports complex form patterns like arrays and nested objects
Enables async form submissions
Allows building custom form components with Formik hooks
Optimizes form performance

# Core Topics

chathuraed chathuraed
[0]
[0]
Updated: 3/7/2026

Quality Score

Top 5%
70
Excellent
Based on code quality & docs
Installation
SYS Universal Install (Auto-Detect)
Cursor IDE Windsurf IDE VS Code IDE
> npx killer-skills add chathuraed/existing_project/references/EXAMPLES.md

Agent Capability Analysis

The formik MCP Server by chathuraed is an open-source Categories.community integration for Claude and other AI agents, enabling seamless task automation and capability expansion. Optimized for how to use formik, formik vs react-hook-form, formik install.

Ideal Agent Persona

Perfect for Frontend Agents building complex React applications needing efficient form state management and validation.

Core Value

Empowers agents to handle form validation with Yup, manage form state and field values, and implement complex form patterns using React and Formik hooks, optimizing form performance with async submissions.

Capabilities Granted for formik MCP Server

Creating dynamic forms with nested objects and arrays
Handling async form submissions with validation
Building custom form components with Formik hooks

! Prerequisites & Limits

  • Requires React environment
  • Limited to form management and validation
Project
SKILL.md
13.1 KB
.cursorrules
1.2 KB
package.json
240 B
Ready
UTF-8

# Tags

[No tags]
SKILL.md
Readonly

Formik Skill

A comprehensive guide for building forms in React using Formik, the most popular open-source form library.

When to use this skill

Use this skill when you need to:

  • Create forms in React applications
  • Handle form validation (with or without Yup)
  • Manage form state, field values, and errors
  • Implement complex form patterns (arrays, nested objects, dynamic fields)
  • Handle async form submissions
  • Build custom form components with Formik hooks
  • Optimize form performance with FastField

Core Concepts

The Formik Component

Formik manages form state and provides helper methods through render props or child functions:

jsx
1import { Formik, Form, Field, ErrorMessage } from 'formik'; 2 3<Formik 4 initialValues={{ email: '', password: '' }} 5 validate={values => { 6 const errors = {}; 7 if (!values.email) { 8 errors.email = 'Required'; 9 } 10 return errors; 11 }} 12 onSubmit={(values, { setSubmitting }) => { 13 setTimeout(() => { 14 alert(JSON.stringify(values, null, 2)); 15 setSubmitting(false); 16 }, 400); 17 }} 18> 19 {({ isSubmitting }) => ( 20 <Form> 21 <Field type="email" name="email" /> 22 <ErrorMessage name="email" component="div" /> 23 <Field type="password" name="password" /> 24 <ErrorMessage name="password" component="div" /> 25 <button type="submit" disabled={isSubmitting}> 26 Submit 27 </button> 28 </Form> 29 )} 30</Formik>

Using Formik Hooks (Recommended)

The modern approach uses hooks for cleaner code:

jsx
1import { useFormik } from 'formik'; 2 3function MyForm() { 4 const formik = useFormik({ 5 initialValues: { 6 firstName: '', 7 lastName: '', 8 email: '', 9 }, 10 onSubmit: values => { 11 alert(JSON.stringify(values, null, 2)); 12 }, 13 }); 14 15 return ( 16 <form onSubmit={formik.handleSubmit}> 17 <input 18 id="firstName" 19 name="firstName" 20 type="text" 21 onChange={formik.handleChange} 22 value={formik.values.firstName} 23 /> 24 25 <input 26 id="email" 27 name="email" 28 type="email" 29 onChange={formik.handleChange} 30 value={formik.values.email} 31 /> 32 33 <button type="submit">Submit</button> 34 </form> 35 ); 36}

Validation

Schema Validation with Yup

Formik integrates seamlessly with Yup for schema-based validation:

jsx
1import * as Yup from 'yup'; 2 3const SignupSchema = Yup.object().shape({ 4 firstName: Yup.string() 5 .min(2, 'Too Short!') 6 .max(50, 'Too Long!') 7 .required('Required'), 8 lastName: Yup.string() 9 .min(2, 'Too Short!') 10 .max(50, 'Too Long!') 11 .required('Required'), 12 email: Yup.string() 13 .email('Invalid email') 14 .required('Required'), 15 age: Yup.number() 16 .positive() 17 .integer() 18 .required('Required'), 19}); 20 21<Formik 22 initialValues={{ 23 firstName: '', 24 lastName: '', 25 email: '', 26 age: '', 27 }} 28 validationSchema={SignupSchema} 29 onSubmit={values => { 30 console.log(values); 31 }} 32> 33 {/* ... */} 34</Formik>

Custom Validation Function

For more control, write custom validation:

jsx
1const validate = values => { 2 const errors = {}; 3 4 if (!values.email) { 5 errors.email = 'Required'; 6 } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)) { 7 errors.email = 'Invalid email address'; 8 } 9 10 if (!values.password) { 11 errors.password = 'Required'; 12 } else if (values.password.length < 8) { 13 errors.password = 'Password must be at least 8 characters'; 14 } 15 16 return errors; 17};

Field-Level Validation

Validate individual fields:

jsx
1function validateEmail(value) { 2 let error; 3 if (!value) { 4 error = 'Required'; 5 } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(value)) { 6 error = 'Invalid email address'; 7 } 8 return error; 9} 10 11<Field name="email" validate={validateEmail} />

Field Components

Basic Field Usage

The Field component handles common input types:

jsx
1<Field name="email" type="email" placeholder="Email" /> 2<Field name="description" as="textarea" rows="5" /> 3<Field name="color" as="select"> 4 <option value="red">Red</option> 5 <option value="green">Green</option> 6 <option value="blue">Blue</option> 7</Field>

Radio Buttons

jsx
1<div role="group"> 2 <label> 3 <Field type="radio" name="contactMethod" value="email" /> 4 Email 5 </label> 6 <label> 7 <Field type="radio" name="contactMethod" value="phone" /> 8 Phone 9 </label> 10</div>

Checkboxes

jsx
1<label> 2 <Field type="checkbox" name="acceptTerms" /> 3 I accept the terms and conditions 4</label> 5 6{/* Checkbox group */} 7<div role="group"> 8 <label> 9 <Field type="checkbox" name="hobbies" value="reading" /> 10 Reading 11 </label> 12 <label> 13 <Field type="checkbox" name="hobbies" value="coding" /> 14 Coding 15 </label> 16</div>

Custom Field Components

jsx
1const MyInput = ({ field, form, ...props }) => { 2 return <input {...field} {...props} />; 3}; 4 5<Field name="email" component={MyInput} />

Displaying Errors

Using ErrorMessage Component

jsx
1<ErrorMessage name="email" /> 2 3{/* Custom error component */} 4<ErrorMessage name="email" component="div" className="error" /> 5 6{/* Render prop for custom styling */} 7<ErrorMessage name="email"> 8 {msg => <div className="error-message">{msg}</div>} 9</ErrorMessage>

Manual Error Display

jsx
1{formik.touched.email && formik.errors.email ? ( 2 <div className="error">{formik.errors.email}</div> 3) : null}

Advanced Patterns

FieldArray for Dynamic Lists

Handle arrays of fields:

jsx
1import { FieldArray } from 'formik'; 2 3<Formik 4 initialValues={{ friends: [''] }} 5 onSubmit={values => console.log(values)} 6> 7 {({ values }) => ( 8 <Form> 9 <FieldArray name="friends"> 10 {({ insert, remove, push }) => ( 11 <div> 12 {values.friends.length > 0 && 13 values.friends.map((friend, index) => ( 14 <div key={index}> 15 <Field name={`friends.${index}`} /> 16 <button type="button" onClick={() => remove(index)}> 17 Remove 18 </button> 19 </div> 20 ))} 21 <button type="button" onClick={() => push('')}> 22 Add Friend 23 </button> 24 </div> 25 )} 26 </FieldArray> 27 <button type="submit">Submit</button> 28 </Form> 29 )} 30</Formik>

Nested Objects

Handle nested form data:

jsx
1initialValues={{ 2 user: { 3 name: '', 4 address: { 5 street: '', 6 city: '', 7 zip: '' 8 } 9 } 10}} 11 12<Field name="user.name" /> 13<Field name="user.address.street" /> 14<Field name="user.address.city" /> 15<Field name="user.address.zip" />

Dependent Fields

Update fields based on other field values:

jsx
1const formik = useFormik({ 2 initialValues: { 3 country: '', 4 state: '' 5 }, 6 onSubmit: values => console.log(values) 7}); 8 9useEffect(() => { 10 // Reset state when country changes 11 if (formik.values.country) { 12 formik.setFieldValue('state', ''); 13 } 14}, [formik.values.country]);

Form Submission

Basic Submission

jsx
1onSubmit={(values, { setSubmitting, setErrors, setStatus, resetForm }) => { 2 // values: form data 3 // setSubmitting: toggle submission state 4 // setErrors: set field errors 5 // setStatus: set form-level status 6 // resetForm: reset form to initial state 7 8 setTimeout(() => { 9 console.log(values); 10 setSubmitting(false); 11 }, 400); 12}

Async Submission with API

jsx
1onSubmit={async (values, { setSubmitting, setErrors }) => { 2 try { 3 const response = await fetch('/api/submit', { 4 method: 'POST', 5 headers: { 'Content-Type': 'application/json' }, 6 body: JSON.stringify(values) 7 }); 8 9 if (!response.ok) { 10 const errors = await response.json(); 11 setErrors(errors); 12 } else { 13 // Handle success 14 alert('Form submitted successfully!'); 15 } 16 } catch (error) { 17 setErrors({ submit: 'Network error occurred' }); 18 } finally { 19 setSubmitting(false); 20 } 21}

Server-Side Validation Errors

jsx
1onSubmit={async (values, { setFieldError, setSubmitting }) => { 2 try { 3 await api.submit(values); 4 } catch (error) { 5 if (error.response?.data?.errors) { 6 // Set individual field errors from server 7 Object.entries(error.response.data.errors).forEach(([field, message]) => { 8 setFieldError(field, message); 9 }); 10 } 11 } finally { 12 setSubmitting(false); 13 } 14}

Performance Optimization

FastField

For large forms, use FastField to prevent unnecessary re-renders:

jsx
1import { FastField } from 'formik'; 2 3// Only re-renders when its own value, error, or touched status changes 4<FastField name="firstName" />

When to use FastField

  • Forms with 30+ fields
  • Fields that don't depend on other field values
  • Fields without complex validation logic

Don't use FastField when:

  • Fields need to react to changes in other fields
  • You're using field-level validation that depends on other values

Common Form Helpers

getFieldProps

Simplify field bindings:

jsx
1<input 2 type="text" 3 {...formik.getFieldProps('firstName')} 4 // Equivalent to: 5 // name="firstName" 6 // value={formik.values.firstName} 7 // onChange={formik.handleChange} 8 // onBlur={formik.handleBlur} 9/>

setFieldValue

Programmatically set field values:

jsx
1formik.setFieldValue('email', 'user@example.com'); 2formik.setFieldValue('user.address.city', 'New York');

resetForm

Reset form to initial or specific values:

jsx
1// Reset to initial values 2formik.resetForm(); 3 4// Reset to new values 5formik.resetForm({ 6 values: { email: '', password: '' } 7});

Form-Level Helpers

Form State Properties

jsx
1formik.values // Current form values 2formik.errors // Validation errors 3formik.touched // Which fields have been visited 4formik.isSubmitting // Submission in progress 5formik.isValid // Form passes validation 6formik.dirty // Form has been modified 7formik.isValidating // Validation in progress

Form Methods

jsx
1formik.handleSubmit() // Submit handler 2formik.handleReset() // Reset handler 3formik.validateForm() // Trigger validation 4formik.setFieldTouched() // Mark field as touched 5formik.setErrors() // Set multiple errors 6formik.setValues() // Set multiple values

Integration Examples

With Material-UI

jsx
1import TextField from '@mui/material/TextField'; 2 3<Field name="email"> 4 {({ field, meta }) => ( 5 <TextField 6 {...field} 7 label="Email" 8 error={meta.touched && Boolean(meta.error)} 9 helperText={meta.touched && meta.error} 10 /> 11 )} 12</Field>

With React Router

Navigate after successful submission:

jsx
1import { useNavigate } from 'react-router-dom'; 2 3function MyForm() { 4 const navigate = useNavigate(); 5 6 const formik = useFormik({ 7 initialValues: { /* ... */ }, 8 onSubmit: async (values) => { 9 await api.submit(values); 10 navigate('/success'); 11 } 12 }); 13 14 return <form onSubmit={formik.handleSubmit}>...</form>; 15}

Best Practices

  1. Always use validationSchema with Yup for complex validation instead of custom validate functions
  2. Use Field components instead of manual input bindings for automatic state management
  3. Handle isSubmitting to disable submit buttons and prevent double submissions
  4. Show errors only after touch using touched to avoid showing errors prematurely
  5. Use getFieldProps for cleaner code when binding inputs
  6. Consider FastField for performance in large forms
  7. Reset forms after success using resetForm() when appropriate
  8. Use setStatus for form-level messages (success, error) that aren't field-specific

Common Pitfalls

  1. Not checking touched before showing errors - shows all errors immediately
  2. Forgetting to set isSubmitting to false - leaves form in submitting state
  3. Using FastField incorrectly - breaks dependent field logic
  4. Not handling async validation errors - API errors get lost
  5. Mutating form values directly - always use setFieldValue or setValues
  6. Missing name attribute on Field components - breaks field binding

Debugging Tips

Check form state in DevTools:

jsx
1<pre>{JSON.stringify(formik, null, 2)}</pre>

Enable Formik debug mode:

jsx
1<Formik 2 enableReinitialize // Reset when initialValues change 3 validateOnChange // Validate on every keystroke (default: true) 4 validateOnBlur // Validate on blur (default: true) 5 validateOnMount // Validate on mount (default: false) 6>

Additional Resources

Quick Reference

Installation:

bash
1npm install formik yup

Basic Form:

jsx
1import { useFormik } from 'formik'; 2 3const formik = useFormik({ 4 initialValues: { email: '' }, 5 onSubmit: values => console.log(values) 6});

With Validation:

jsx
1import * as Yup from 'yup'; 2 3validationSchema: Yup.object({ 4 email: Yup.string().email().required() 5})

Related Skills

Looking for an alternative to formik or building a Categories.community AI Agent? Explore these related open-source MCP Servers.

View All

widget-generator

Logo of f
f

widget-generator is an open-source AI agent skill for creating widget plugins that are injected into prompt feeds on prompts.chat. It supports two rendering modes: standard prompt widgets using default PromptCard styling and custom render widgets built as full React components.

149.6k
0
Design

chat-sdk

Logo of lobehub
lobehub

chat-sdk is a unified TypeScript SDK for building chat bots across multiple platforms, providing a single interface for deploying bot logic.

73.0k
0
Communication

zustand

Logo of lobehub
lobehub

The ultimate space for work and life — to find, build, and collaborate with agent teammates that grow with you. We are taking agent harness to the next level — enabling multi-agent collaboration, effortless agent team design, and introducing agents as the unit of work interaction.

72.8k
0
Communication

data-fetching

Logo of lobehub
lobehub

The ultimate space for work and life — to find, build, and collaborate with agent teammates that grow with you. We are taking agent harness to the next level — enabling multi-agent collaboration, effortless agent team design, and introducing agents as the unit of work interaction.

72.8k
0
Communication