├── README.md ├── website ├── README.md ├── static │ ├── img │ │ ├── favicon.png │ │ ├── formik.png │ │ ├── oss_logo.png │ │ ├── pattern.png │ │ ├── formik-og.png │ │ ├── logo-white.png │ │ ├── logos │ │ │ ├── artsy.png │ │ │ ├── frameio.png │ │ │ ├── priceline.png │ │ │ ├── campusjaeger.png │ │ │ ├── letgo-logo.png │ │ │ ├── state-street.png │ │ │ ├── gitconnected-logo.png │ │ │ ├── gremlin.svg │ │ │ ├── viacom.svg │ │ │ ├── sony.svg │ │ │ ├── nokia.svg │ │ │ ├── capsule.svg │ │ │ ├── zauberware-logo.svg │ │ │ ├── airbnb.svg │ │ │ ├── gusto.svg │ │ │ ├── nasdaq.svg │ │ │ └── cargurus.svg │ │ ├── formik-twitter.png │ │ └── formik-mark.svg │ ├── fonts │ │ ├── FormikSans-Bold.ttf │ │ ├── FormikSans-Bold.woff │ │ ├── FormikSans-Book.ttf │ │ ├── FormikSans-Book.woff │ │ ├── FormikSans-Demi.ttf │ │ ├── FormikSans-Demi.woff │ │ ├── FormikSans-Light.ttf │ │ ├── FormikSans-Mono.ttf │ │ ├── FormikSans-Mono.woff │ │ ├── FormikSans-Bold.woff2 │ │ ├── FormikSans-Book.woff2 │ │ ├── FormikSans-Demi.woff2 │ │ ├── FormikSans-Light.woff │ │ ├── FormikSans-Light.woff2 │ │ ├── FormikSans-Medium.ttf │ │ ├── FormikSans-Medium.woff │ │ ├── FormikSans-Mono.woff2 │ │ └── FormikSans-Medium.woff2 │ ├── browserconfig.xml │ ├── css │ │ ├── code-blocks-buttons.css │ │ └── fonts.css │ └── js │ │ └── code-blocks-buttons.js ├── versions.json ├── package.json ├── versioned_docs │ ├── version-1.2.0 │ │ ├── api │ │ │ ├── form.md │ │ │ └── connect.md │ │ ├── guides │ │ │ ├── form-submission.md │ │ │ ├── react-native.md │ │ │ └── arrays.md │ │ └── resources.md │ ├── version-1.3.2 │ │ ├── api │ │ │ └── form.md │ │ └── guides │ │ │ └── react-native.md │ ├── version-2.1.4 │ │ ├── examples.md │ │ └── api │ │ │ └── useFormik.md │ ├── version-2.0.3 │ │ ├── 3rd-party-bindings.md │ │ ├── api │ │ │ ├── connect.md │ │ │ ├── useFormikContext.md │ │ │ └── useFormik.md │ │ └── guides │ │ │ ├── react-native.md │ │ │ ├── arrays.md │ │ │ └── form-submission.md │ ├── version-1.4.3 │ │ └── guides │ │ │ └── react-native.md │ ├── version-1.5.0 │ │ └── guides │ │ │ └── form-submission.md │ ├── version-1.3.0 │ │ └── resources.md │ └── version-1.4.2 │ │ └── resources.md ├── sidebars.json ├── versioned_sidebars │ ├── version-1.2.0-sidebars.json │ ├── version-1.3.0-sidebars.json │ ├── version-2.0.3-sidebars.json │ └── version-2.1.4-sidebars.json └── pages │ └── en │ ├── users.js │ └── help.js ├── MIGRATING-v2.md ├── packages ├── formik-native │ ├── .gitignore │ ├── test │ │ └── blah.test.ts │ ├── README.md │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ ├── CONTRIBUTING.md │ └── package.json └── formik │ ├── test │ ├── testHelpers.ts │ ├── setupTests.ts │ ├── types.test.tsx │ ├── ErrorMessage.test.tsx │ └── yupHelpers.test.ts │ ├── .eslintrc.js │ ├── types │ ├── global.d.ts │ └── index.d.ts │ ├── src │ ├── index.tsx │ ├── FormikContext.tsx │ ├── Form.tsx │ ├── connect.tsx │ └── ErrorMessage.tsx │ ├── .gitignore │ ├── .size-snapshot.json │ └── tsconfig.json ├── .codesandbox └── ci.json ├── .github ├── ISSUE_TEMPLATE │ ├── Documentation.md │ ├── Question.md │ ├── Feature_request.md │ └── Bug_report.md ├── CONTRIBUTING.md ├── stale.yml ├── FUNDING.yml ├── workflows │ ├── test.yml │ └── release.yml └── CODE_OF_CONDUCT.md ├── dist ├── index.js ├── index.d.ts ├── ErrorMessage.d.ts ├── FormikContext.d.ts ├── connect.d.ts ├── FastField.d.ts ├── Field.d.ts ├── withFormik.d.ts ├── FieldArray.d.ts ├── Formik.d.ts └── utils.d.ts ├── now.json ├── tsconfig.json ├── .gitignore ├── examples ├── basic │ ├── README.md │ ├── package.json │ └── index.js ├── checkboxes │ ├── README.md │ ├── package.json │ └── index.js ├── field-arrays │ ├── README.md │ ├── package.json │ └── index.js ├── radio-group │ ├── README.md │ ├── package.json │ └── index.js ├── dependent-fields │ ├── styles.css │ ├── README.md │ └── package.json ├── async-submission │ ├── README.md │ ├── package.json │ └── index.js ├── dependent-fields-async-api-request │ ├── styles.css │ ├── README.md │ ├── package.json │ └── index.js ├── basic-typescript │ ├── README.md │ ├── index.html │ ├── tsconfig.json │ ├── package.json │ └── index.tsx ├── instant-feedback │ ├── package.json │ └── README.md ├── Debug.js ├── SyncValidation.js ├── AsyncValidation.js ├── withFormik.js ├── FastField.js ├── DebouncedAutoSave.js ├── SchemaValidation.js ├── CombinedValidations.js ├── ErrorMessage.js ├── FieldLevelValidation.js ├── ValidateFieldWithSchema.js └── CustomInputs.js ├── SECURITY.md ├── lerna.json ├── docs ├── api │ ├── form.md │ ├── connect.md │ ├── useFormikContext.md │ └── useFormik.md ├── examples.md ├── 3rd-party-bindings.md ├── guides │ ├── react-native.md │ ├── form-submission.md │ └── arrays.md └── manifest.json ├── tsconfig.base.json └── LICENSE /README.md: -------------------------------------------------------------------------------- 1 | ./packages/formik/README.md -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Formik Website. 2 | -------------------------------------------------------------------------------- /MIGRATING-v2.md: -------------------------------------------------------------------------------- 1 | ./packages/formik/MIGRATING-v2.md -------------------------------------------------------------------------------- /website/static/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/img/favicon.png -------------------------------------------------------------------------------- /website/static/img/formik.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/img/formik.png -------------------------------------------------------------------------------- /website/static/img/oss_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/img/oss_logo.png -------------------------------------------------------------------------------- /website/static/img/pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/img/pattern.png -------------------------------------------------------------------------------- /website/static/img/formik-og.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/img/formik-og.png -------------------------------------------------------------------------------- /website/static/img/logo-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/img/logo-white.png -------------------------------------------------------------------------------- /website/static/img/logos/artsy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/img/logos/artsy.png -------------------------------------------------------------------------------- /website/static/img/logos/frameio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/img/logos/frameio.png -------------------------------------------------------------------------------- /website/static/img/formik-twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/img/formik-twitter.png -------------------------------------------------------------------------------- /website/static/img/logos/priceline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/img/logos/priceline.png -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Bold.ttf -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Bold.woff -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Book.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Book.ttf -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Book.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Book.woff -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Demi.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Demi.ttf -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Demi.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Demi.woff -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Light.ttf -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Mono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Mono.ttf -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Mono.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Mono.woff -------------------------------------------------------------------------------- /website/static/img/logos/campusjaeger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/img/logos/campusjaeger.png -------------------------------------------------------------------------------- /website/static/img/logos/letgo-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/img/logos/letgo-logo.png -------------------------------------------------------------------------------- /website/static/img/logos/state-street.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/img/logos/state-street.png -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Bold.woff2 -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Book.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Book.woff2 -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Demi.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Demi.woff2 -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Light.woff -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Light.woff2 -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Medium.ttf -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Medium.woff -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Mono.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Mono.woff2 -------------------------------------------------------------------------------- /packages/formik-native/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | .rts2_cache_cjs 5 | .rts2_cache_esm 6 | .rts2_cache_umd 7 | dist 8 | -------------------------------------------------------------------------------- /packages/formik-native/test/blah.test.ts: -------------------------------------------------------------------------------- 1 | describe('blah', () => { 2 | it('works', () => { 3 | expect(1).toEqual(1); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /website/static/fonts/FormikSans-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/fonts/FormikSans-Medium.woff2 -------------------------------------------------------------------------------- /website/static/img/logos/gitconnected-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius/formik/master/website/static/img/logos/gitconnected-logo.png -------------------------------------------------------------------------------- /.codesandbox/ci.json: -------------------------------------------------------------------------------- 1 | { 2 | "sandboxes": ["ooh2y"], 3 | "buildCommand": "build", 4 | "packages": ["packages/formik", "packages/formik-native"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/formik-native/README.md: -------------------------------------------------------------------------------- 1 | # Formik Native 2 | 3 | ``` 4 | yarn add formik formik-native 5 | ``` 6 | 7 | This is an experimental package. DO NOT USE IN PRODUCTION. 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Documentation.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41B Documentation" 3 | about: Imrovements or suggestions of Formik documentation 4 | --- 5 | 6 | ## 📖 Documentation 7 | -------------------------------------------------------------------------------- /packages/formik/test/testHelpers.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:no-empty 2 | export const noop = () => {}; 3 | 4 | export const sleep = (ms: number) => 5 | new Promise(resolve => setTimeout(resolve, ms)); 6 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict' 3 | 4 | if (process.env.NODE_ENV === 'production') { 5 | module.exports = require('./formik.cjs.production.min.js') 6 | } else { 7 | module.exports = require('./formik.cjs.development.js') 8 | } 9 | -------------------------------------------------------------------------------- /now.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "formik-docs", 3 | "version": 2, 4 | "builds": [{ 5 | "src": "package.json", 6 | "use": "@now/static-build", 7 | "config": { 8 | "distDir": "website/build" 9 | } 10 | }] 11 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "formik": ["./packages/react/src"], 7 | "formik-native": ["./packages/react-native/src"] 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/formik/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | 'react-app', 4 | 'prettier/@typescript-eslint', 5 | 'plugin:prettier/recommended', 6 | ], 7 | settings: { 8 | react: { 9 | version: 'detect', 10 | }, 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /packages/formik/types/global.d.ts: -------------------------------------------------------------------------------- 1 | // Declare global variables for TypeScript and VSCode. 2 | // Do not rename this file or move these types into index.d.ts 3 | // @see https://code.visualstudio.com/docs/nodejs/working-with-javascript#_global-variables-and-type-checking 4 | declare const __DEV__: boolean; 5 | -------------------------------------------------------------------------------- /website/static/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #ffffff 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | compiled 3 | *.log 4 | coverage 5 | .DS_Store 6 | next.d.ts 7 | legacy.d.ts 8 | .idea 9 | *.orig 10 | 11 | node_modules 12 | package-lock.json 13 | yarn.lock 14 | !/yarn.lock 15 | 16 | website/translated_docs 17 | website/build 18 | website/yarn.lock 19 | website/node_modules 20 | website/i18n 21 | -------------------------------------------------------------------------------- /examples/basic/README.md: -------------------------------------------------------------------------------- 1 | # Formik Basic Example 2 | 3 | This example demonstrates how to use Formik in it's most basic way. 4 | 5 | [![Edit formik-example-basic](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/jaredpalmer/formik/tree/master/examples/basic?fontsize=14&hidenavigation=1&theme=dark) 6 | -------------------------------------------------------------------------------- /examples/checkboxes/README.md: -------------------------------------------------------------------------------- 1 | # Formik Checkboxes 2 | 3 | This example demonstrates how to use Formik with a checkbox group. 4 | 5 | [![Edit formik-example-checkboxes](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/jaredpalmer/formik/tree/master/examples/checkboxes?fontsize=14&hidenavigation=1&theme=dark) 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "❓Question" 3 | about: 'Have a question? Checkout the #formik channel on Reactiflux Discord channel 4 | or on Spectrum.' 5 | --- 6 | 7 | ## ❓Question 8 | 9 | Seriously, for immediate help, just ask your question on the #formik channel on [Reactiflux](https://discordapp.com/invite/MbKwYuq). 10 | -------------------------------------------------------------------------------- /examples/field-arrays/README.md: -------------------------------------------------------------------------------- 1 | # Formik Arrays Example 2 | 3 | This example demonstrates how to work with array fields in Formik. 4 | 5 | [![Edit formik-example-field-arrays](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/jaredpalmer/formik/tree/master/examples/field-arrays?fontsize=14&hidenavigation=1&theme=dark) 6 | -------------------------------------------------------------------------------- /examples/radio-group/README.md: -------------------------------------------------------------------------------- 1 | # Formik Radio Group Example 2 | 3 | This example demonstrates how to create a radio group with Formik. 4 | 5 | [![Edit formik-example-radio-group](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/jaredpalmer/formik/tree/master/examples/radio-group?fontsize=14&hidenavigation=1&theme=dark) 6 | -------------------------------------------------------------------------------- /examples/dependent-fields/styles.css: -------------------------------------------------------------------------------- 1 | .App { 2 | font-family: sans-serif; 3 | max-width: 500px; 4 | } 5 | 6 | .section { 7 | padding: 10px; 8 | border: 1px solid purple; 9 | border-radius: 4px; 10 | margin-bottom: 20px; 11 | } 12 | 13 | label, 14 | input { 15 | display: block; 16 | } 17 | label, 18 | button { 19 | margin-top: 1rem; 20 | } 21 | -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './Formik'; 2 | export * from './Field'; 3 | export * from './Form'; 4 | export * from './withFormik'; 5 | export * from './FieldArray'; 6 | export * from './utils'; 7 | export * from './types'; 8 | export * from './connect'; 9 | export * from './ErrorMessage'; 10 | export * from './FormikContext'; 11 | export * from './FastField'; 12 | -------------------------------------------------------------------------------- /examples/async-submission/README.md: -------------------------------------------------------------------------------- 1 | # Formik Async Submission 2 | 3 | This example demonstrates how to use async/await to submit a Formik form. 4 | 5 | [![Edit formik-example-async-submission](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/jaredpalmer/formik/tree/master/examples/async-submission?fontsize=14&hidenavigation=1&theme=dark) 6 | -------------------------------------------------------------------------------- /examples/dependent-fields-async-api-request/styles.css: -------------------------------------------------------------------------------- 1 | .App { 2 | font-family: sans-serif; 3 | max-width: 500px; 4 | } 5 | 6 | .section { 7 | padding: 10px; 8 | border: 1px solid purple; 9 | border-radius: 4px; 10 | margin-bottom: 20px; 11 | } 12 | 13 | label, 14 | input { 15 | display: block; 16 | } 17 | label, 18 | button { 19 | margin-top: 1rem; 20 | } 21 | -------------------------------------------------------------------------------- /packages/formik/src/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Formik'; 2 | export * from './Field'; 3 | export * from './Form'; 4 | export * from './withFormik'; 5 | export * from './FieldArray'; 6 | export * from './utils'; 7 | export * from './types'; 8 | export * from './connect'; 9 | export * from './ErrorMessage'; 10 | export * from './FormikContext'; 11 | export * from './FastField'; 12 | -------------------------------------------------------------------------------- /examples/basic-typescript/README.md: -------------------------------------------------------------------------------- 1 | # Formik TypeScript Example 2 | 3 | This example demonstrates how to get started with Formik and [TypeScript](https://typescriptlang.org) 4 | 5 | [![Edit formik-example-basic-typescript](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/jaredpalmer/formik/tree/master/examples/basic-typescript?fontsize=14&hidenavigation=1&theme=dark) 6 | -------------------------------------------------------------------------------- /dist/ErrorMessage.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | export interface ErrorMessageProps { 3 | name: string; 4 | className?: string; 5 | component?: string | React.ComponentType; 6 | children?: (errorMessage: string) => React.ReactNode; 7 | render?: (errorMessage: string) => React.ReactNode; 8 | } 9 | export declare const ErrorMessage: React.ComponentType; 10 | -------------------------------------------------------------------------------- /examples/dependent-fields/README.md: -------------------------------------------------------------------------------- 1 | # Formik Dependent Fields Example 2 | 3 | This is an example of how to set the value of one field based on the current values of other fields in Formik v2. 4 | 5 | [![Edit formik-example-dependent-fields](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/jaredpalmer/formik/tree/master/examples/dependent-fields?fontsize=14&hidenavigation=1&theme=dark) 6 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | 2.x.x | :white_check_mark: | 8 | | 1.5.x | :white_check_mark: | 9 | | <= 1.4 | :x: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | Send a Twitter DM to [@jaredpalmer](http://twitter.com/@jaredpalmer) or an email to security@jaredpalmer.com 14 | 15 | -------------------------------------------------------------------------------- /dist/FormikContext.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { FormikContextType } from './types'; 3 | export declare const FormikContext: React.Context>; 4 | export declare const FormikProvider: React.Provider>; 5 | export declare const FormikConsumer: React.Consumer>; 6 | export declare function useFormikContext(): FormikContextType; 7 | -------------------------------------------------------------------------------- /dist/connect.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { FormikContextType } from './types'; 3 | /** 4 | * Connect any component to Formik context, and inject as a prop called `formik`; 5 | * @param Comp React Component 6 | */ 7 | export declare function connect(Comp: React.ComponentType; 9 | }>): React.ComponentType; 10 | -------------------------------------------------------------------------------- /examples/basic-typescript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Playground 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmClient": "yarn", 3 | "useWorkspaces": true, 4 | "packages": [ 5 | "packages/*" 6 | ], 7 | "command": { 8 | "version": { 9 | "exact": true 10 | }, 11 | "publish": { 12 | "npmClient": "npm", 13 | "allowBranch": [ 14 | "master", 15 | "canary" 16 | ], 17 | "registry": "https://registry.npmjs.org/" 18 | } 19 | }, 20 | "version": "2.1.4" 21 | } 22 | -------------------------------------------------------------------------------- /packages/formik/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | compiled 4 | *.log 5 | coverage 6 | .DS_Store 7 | next.d.ts 8 | legacy.d.ts 9 | .idea 10 | *.orig 11 | .DS_Store 12 | 13 | node_modules 14 | 15 | lib/core/metadata.js 16 | lib/core/MetadataBlog.js 17 | 18 | website/translated_docs 19 | website/build/ 20 | website/yarn.lock 21 | website/node_modules 22 | website/i18n/* 23 | .rts2_cache_es 24 | .rts2_cache_esm 25 | .rts2_cache_cjs 26 | .rts2_cache_umd -------------------------------------------------------------------------------- /website/versions.json: -------------------------------------------------------------------------------- 1 | [ 2 | "2.1.4", 3 | "2.1.2", 4 | "2.1.0", 5 | "2.0.9", 6 | "2.0.8", 7 | "2.0.7", 8 | "2.0.6", 9 | "2.0.5", 10 | "2.0.4", 11 | "2.0.3", 12 | "1.5.8", 13 | "1.5.7", 14 | "1.5.5", 15 | "1.5.4", 16 | "1.5.3", 17 | "1.5.2", 18 | "1.5.1", 19 | "1.5.0", 20 | "1.4.4", 21 | "1.4.3", 22 | "1.4.2", 23 | "1.4.1", 24 | "1.4.0", 25 | "1.3.2", 26 | "1.3.1", 27 | "1.3.0", 28 | "1.2.0" 29 | ] 30 | -------------------------------------------------------------------------------- /examples/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "formik-example-basic", 3 | "version": "0.1.0", 4 | "description": "This example demonstrates how to use Formik in it's most basic way", 5 | "main": "index.js", 6 | "dependencies": { 7 | "react": "^16.12.0", 8 | "react-dom": "^16.12.0", 9 | "react-scripts": "3.3.0", 10 | "formik": "latest" 11 | }, 12 | "prettier": { 13 | "trailingComma": "es5", 14 | "singleQuote": true, 15 | "semi": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/checkboxes/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "formik-example-checkboxes", 3 | "version": "0.1.0", 4 | "description": "This example demonstrates how to use Formik with a checkbox group", 5 | "main": "index.js", 6 | "dependencies": { 7 | "react": "^16.12.0", 8 | "react-dom": "^16.12.0", 9 | "react-scripts": "3.3.0", 10 | "formik": "latest" 11 | }, 12 | "prettier": { 13 | "trailingComma": "es5", 14 | "singleQuote": true, 15 | "semi": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/instant-feedback/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "accesible-instant-feedback-with-formik", 3 | "version": "0.1.0", 4 | "description": "", 5 | "main": "index.js", 6 | "dependencies": { 7 | "formik": "latest", 8 | "react": "^16.12.0", 9 | "react-dom": "^16.12.0", 10 | "react-scripts": "3.3.0", 11 | "yup": "0.28.1" 12 | }, 13 | "prettier": { 14 | "trailingComma": "es5", 15 | "singleQuote": true, 16 | "semi": true 17 | }, 18 | "keywords": [] 19 | } -------------------------------------------------------------------------------- /examples/field-arrays/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "formik-example-field-arrays", 3 | "version": "0.1.0", 4 | "description": "This example demonstrates how to work with array fields in Formik", 5 | "main": "index.js", 6 | "dependencies": { 7 | "react": "^16.12.0", 8 | "react-dom": "^16.12.0", 9 | "react-scripts": "3.3.0", 10 | "formik": "latest" 11 | }, 12 | "prettier": { 13 | "trailingComma": "es5", 14 | "singleQuote": true, 15 | "semi": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/radio-group/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "formik-example-radio-group", 3 | "version": "0.1.0", 4 | "description": "This example demonstrates how to create a radio group with Formik", 5 | "main": "index.js", 6 | "dependencies": { 7 | "react": "^16.12.0", 8 | "react-dom": "^16.12.0", 9 | "react-scripts": "3.3.0", 10 | "formik": "latest" 11 | }, 12 | "prettier": { 13 | "trailingComma": "es5", 14 | "singleQuote": true, 15 | "semi": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/formik-native/src/index.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { NativeSyntheticEvent, NativeTouchEvent } from 'react-native'; 3 | import { useFormikContext } from 'formik'; 4 | 5 | export function useSubmitButton() { 6 | const { submitForm } = useFormikContext(); 7 | const handlePress = React.useCallback( 8 | (_ev: NativeSyntheticEvent) => { 9 | submitForm(); 10 | }, 11 | [submitForm] 12 | ); 13 | return { onPress: handlePress }; 14 | } 15 | -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "examples": "docusaurus-examples", 4 | "start": "docusaurus-start", 5 | "build": "docusaurus-build", 6 | "publish-gh-pages": "docusaurus-publish", 7 | "write-translations": "docusaurus-write-translations", 8 | "version": "docusaurus-version", 9 | "rename-version": "docusaurus-rename-version" 10 | }, 11 | "devDependencies": { 12 | "docusaurus": "^1.14.4" 13 | }, 14 | "engines": { 15 | "node": "12.x" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/async-submission/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "formik-example-async-submission", 3 | "version": "0.1.0", 4 | "description": "This example demonstrates how to use async/await to submit a Formik form", 5 | "main": "index.js", 6 | "dependencies": { 7 | "react": "^16.12.0", 8 | "react-dom": "^16.12.0", 9 | "react-scripts": "3.3.0", 10 | "formik": "latest" 11 | }, 12 | "prettier": { 13 | "trailingComma": "es5", 14 | "singleQuote": true, 15 | "semi": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /docs/api/form.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: form 3 | title:
4 | custom_edit_url: https://github.com/jaredpalmer/formik/edit/master/docs/api/form.md 5 | --- 6 | 7 | Form is a small wrapper around an HTML `` element that automatically hooks into Formik's `handleSubmit` and `handleReset`. All other props are passed directly through to the DOM node. 8 | 9 | ```jsx 10 | // so... 11 | 12 | 13 | // is identical to this... 14 | 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/examples.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: examples 3 | title: Examples 4 | --- 5 | 6 | ## Dependent Fields 7 | 8 | Programmatically set the value of one field based on the current values of other fields. 9 | 10 | https://codesandbox.io/s/formik-v2x-dependent-fields-r0n0v 11 | 12 | ## Dependent Fields based on Async API Request 13 | 14 | In this example, one field's value is set by making an async API based on the current values of two other fields. 15 | 16 | https://codesandbox.io/s/formik-v2x-dependent-field-with-async-api-request-4yjrv 17 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Formik 2 | 3 | 1. Fork this repository to your own GitHub account and then clone it to your local device. 4 | 2. Install the dependencies: `yarn install` 5 | 3. Run `yarn link` to link the local repo to NPM 6 | 4. Run `cd packages/formik && yarn start` to build and watch for code changes 7 | 5. Run `yarn test` to start Jest 8 | 7. Then npm link this repo inside any other project on your local dev with `yarn link formik` 9 | 8. Then you can use your local version of Formik within your project 10 | 11 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.2.0/api/form.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: version-1.2.0-form 3 | title: 4 | custom_edit_url: https://github.com/jaredpalmer/formik/edit/master/docs/api/form.md 5 | original_id: form 6 | --- 7 | 8 | Form is a small wrapper around an HTML `` element that automatically hooks into Formik's `handleSubmit`. All other props are passed directly through to the DOM node. 9 | 10 | ```jsx 11 | // so... 12 | 13 | 14 | // is identical to this... 15 | 16 | ``` 17 | -------------------------------------------------------------------------------- /examples/dependent-fields/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "formik-example-dependent-fields", 3 | "version": "0.1.0", 4 | "description": "This is an example of how to set the value of one field based on the current values of other fields in Formik v2", 5 | "main": "index.js", 6 | "dependencies": { 7 | "react": "^16.12.0", 8 | "react-dom": "^16.12.0", 9 | "react-scripts": "3.3.0", 10 | "formik": "latest" 11 | }, 12 | "prettier": { 13 | "trailingComma": "es5", 14 | "singleQuote": true, 15 | "semi": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/dependent-fields-async-api-request/README.md: -------------------------------------------------------------------------------- 1 | # Dependent Formik fields with Async API Request 2 | 3 | This is an example of a complex dependent field in Formik v2. In this example, one field's value is set by making an asynchronous API request based on the current values of other fields. 4 | 5 | [![Edit formik-example-dependent-fields-async-api-request](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/jaredpalmer/formik/tree/master/examples/dependent-fields-async-api-request?fontsize=14&hidenavigation=1&theme=dark) 6 | -------------------------------------------------------------------------------- /examples/basic-typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": false, 4 | "target": "es5", 5 | "module": "commonjs", 6 | "jsx": "react", 7 | "moduleResolution": "node", 8 | "noImplicitAny": false, 9 | "noUnusedLocals": false, 10 | "noUnusedParameters": false, 11 | "removeComments": true, 12 | "strictNullChecks": true, 13 | "preserveConstEnums": true, 14 | "sourceMap": true, 15 | "lib": ["es2015", "es2016", "dom"], 16 | "baseUrl": ".", 17 | "types": ["node"] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.3.2/api/form.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: version-1.3.2-form 3 | title: 4 | custom_edit_url: https://github.com/jaredpalmer/formik/edit/master/docs/api/form.md 5 | original_id: form 6 | --- 7 | 8 | Form is a small wrapper around an HTML `` element that automatically hooks into Formik's `handleSubmit` and `handleReset`. All other props are passed directly through to the DOM node. 9 | 10 | ```jsx 11 | // so... 12 | 13 | 14 | // is identical to this... 15 | 16 | ``` 17 | -------------------------------------------------------------------------------- /website/versioned_docs/version-2.1.4/examples.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: version-2.1.4-examples 3 | title: Examples 4 | original_id: examples 5 | --- 6 | 7 | ## Dependent Fields 8 | 9 | Programmatically set the value of one field based on the current values of other fields. 10 | 11 | https://codesandbox.io/s/formik-v2x-dependent-fields-r0n0v 12 | 13 | ## Dependent Fields based on Async API Request 14 | 15 | In this example, one field's value is set by making an async API based on the current values of two other fields. 16 | 17 | https://codesandbox.io/s/formik-v2x-dependent-field-with-async-api-request-4yjrv 18 | -------------------------------------------------------------------------------- /examples/dependent-fields-async-api-request/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "formik-example-dependent-fields-async-api-request", 3 | "version": "0.1.0", 4 | "description": "This is an example of how to set the value of one field based on an async API request that uses the current values of other fields in Formik v2", 5 | "main": "index.js", 6 | "dependencies": { 7 | "react": "^16.12.0", 8 | "react-dom": "^16.12.0", 9 | "react-scripts": "3.3.0", 10 | "formik": "latest" 11 | }, 12 | "prettier": { 13 | "trailingComma": "es5", 14 | "singleQuote": true, 15 | "semi": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 3600 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - enhancement 8 | - pinned 9 | - RFC 10 | - bug 11 | - in progress 12 | - 2.0 13 | # Label to use when marking an issue as stale 14 | staleLabel: stale 15 | # Comment to post when marking an issue as stale. Set to `false` to disable 16 | markComment: false 17 | # Comment to post when closing a stale issue. Set to `false` to disable 18 | closeComment: false 19 | -------------------------------------------------------------------------------- /examples/basic-typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "formik-basic-typescript-example", 3 | "version": "0.1.0", 4 | "description": "This example demonstrates how to use Formik with TypeScript", 5 | "main": "index.tsx", 6 | "dependencies": { 7 | "@types/react-dom": "^16.8.4", 8 | "@types/react": "^16.9.11", 9 | "formik": "latest", 10 | "parcel": "latest", 11 | "react-app-polyfill": "^1.0.5", 12 | "react-dom": "latest", 13 | "react": "latest", 14 | "typescript": "latest" 15 | }, 16 | "prettier": { 17 | "trailingComma": "es5", 18 | "singleQuote": true, 19 | "semi": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "pretty": true, 5 | "noImplicitAny": true, 6 | "strictNullChecks": true, 7 | "strictFunctionTypes": true, 8 | "strictPropertyInitialization": true, 9 | "noImplicitThis": true, 10 | "alwaysStrict": true, 11 | "stripInternal": true, 12 | "noUnusedLocals": true, 13 | "noUnusedParameters": true, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "emitDecoratorMetadata": false, 17 | "experimentalDecorators": false, 18 | "esModuleInterop": true, 19 | "allowSyntheticDefaultImports": true, 20 | } 21 | } -------------------------------------------------------------------------------- /website/sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "docs": { 3 | "Getting Started": ["overview", "tutorial", "migrating-v2", "resources"], 4 | "Guides": [ 5 | "guides/validation", 6 | "guides/arrays", 7 | "guides/typescript", 8 | "guides/react-native", 9 | "guides/form-submission" 10 | ], 11 | "API Reference": [ 12 | "api/connect", 13 | "api/errormessage", 14 | "api/fastfield", 15 | "api/field", 16 | "api/fieldarray", 17 | "api/form", 18 | "api/formik", 19 | "api/useField", 20 | "api/useFormik", 21 | "api/useFormikContext", 22 | "api/withFormik" 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /docs/3rd-party-bindings.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3rd Party Bindings 3 | original_id: 3rd-party-bindings 4 | --- 5 | 6 | If you would like to use Formik with a UI framework, you'll probably want to create a wrapper component that binds Formik's props and callbacks. 7 | 8 | A few popular frameworks have open source wrappers readily available: 9 | 10 | - [Ant Design](https://github.com/jannikbuschke/formik-antd) 11 | - [Fabric](https://github.com/kmees/formik-office-ui-fabric-react) 12 | - [Material UI](https://github.com/stackworx/formik-material-ui) 13 | - [Reactstrap](https://github.com/shoaibkhan94/reactstrap-formik) 14 | - [Semantic UI](https://github.com/turner-industries/formik-semantic-ui) 15 | -------------------------------------------------------------------------------- /examples/instant-feedback/README.md: -------------------------------------------------------------------------------- 1 | # Formik Accessible Instant Feedback Example 2 | 3 | Instant feedback during typing can be extremely helpful in certain situations. For example, checking the validity (or availability) of a username shouldn't require the user to resubmit the form (multiple times). Providing instant feedback while users are typing can allow them to experiment more easily until they find valid input value (like a suitable username). Note: This isn't always optimal, use your judgement. 4 | 5 | [![Edit formik-example-basic](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/jaredpalmer/formik/tree/master/examples/basic?fontsize=14&hidenavigation=1&theme=dark) 6 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: formik 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /packages/formik/src/FormikContext.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { FormikContextType } from './types'; 3 | import invariant from 'tiny-warning'; 4 | 5 | export const FormikContext = React.createContext>( 6 | undefined as any 7 | ); 8 | export const FormikProvider = FormikContext.Provider; 9 | export const FormikConsumer = FormikContext.Consumer; 10 | 11 | export function useFormikContext() { 12 | const formik = React.useContext>(FormikContext); 13 | 14 | invariant( 15 | !!formik, 16 | `Formik context is undefined, please verify you are calling useFormikContext() as child of a component.` 17 | ); 18 | 19 | return formik; 20 | } 21 | -------------------------------------------------------------------------------- /website/static/css/code-blocks-buttons.css: -------------------------------------------------------------------------------- 1 | /* "Copy" code block button */ 2 | pre { 3 | position: relative; 4 | } 5 | 6 | pre .btnIcon { 7 | position: absolute; 8 | top: 4px; 9 | z-index: 2; 10 | cursor: pointer; 11 | border: 1px solid transparent; 12 | padding: 0; 13 | color: #000; 14 | background-color: transparent; 15 | height: 30px; 16 | transition: all .25s ease-out; 17 | } 18 | 19 | pre .btnIcon:hover { 20 | text-decoration: none; 21 | } 22 | 23 | .btnIcon__body { 24 | align-items: center; 25 | display: flex; 26 | } 27 | 28 | .btnIcon svg { 29 | fill: currentColor; 30 | margin-right: .4em; 31 | } 32 | 33 | .btnIcon__label { 34 | font-size: 11px; 35 | } 36 | 37 | .btnClipboard { 38 | right: 10px; 39 | } -------------------------------------------------------------------------------- /dist/FastField.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { FormikProps, GenericFieldHTMLAttributes, FieldMetaProps, FieldInputProps } from './types'; 3 | import { FieldConfig } from './Field'; 4 | export interface FastFieldProps { 5 | field: FieldInputProps; 6 | meta: FieldMetaProps; 7 | form: FormikProps; 8 | } 9 | export declare type FastFieldConfig = FieldConfig & { 10 | /** Override FastField's default shouldComponentUpdate */ 11 | shouldUpdate?: (nextProps: T & GenericFieldHTMLAttributes, props: {}) => boolean; 12 | }; 13 | export declare type FastFieldAttributes = GenericFieldHTMLAttributes & FastFieldConfig & T; 14 | export declare const FastField: React.ComponentType; 15 | -------------------------------------------------------------------------------- /website/versioned_docs/version-2.0.3/3rd-party-bindings.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: version-2.0.3-3rd-party-bindings 3 | title: 3rd Party Bindings 4 | original_id: 3rd-party-bindings 5 | --- 6 | 7 | If you would like to use Formik with a UI framework, you'll probably want to create a wrapper component that binds Formik's props and callbacks. 8 | 9 | A few popular frameworks have open source wrappers readily available: 10 | 11 | - [Ant Design](https://github.com/jannikbuschke/formik-antd) 12 | - [Fabric](https://github.com/kmees/formik-office-ui-fabric-react) 13 | - [Material UI](https://github.com/stackworx/formik-material-ui) 14 | - [Reactstrap](https://github.com/shoaibkhan94/reactstrap-formik) 15 | - [Semantic UI](https://github.com/turner-industries/formik-semantic-ui) 16 | -------------------------------------------------------------------------------- /packages/formik/test/setupTests.ts: -------------------------------------------------------------------------------- 1 | const consoleError = console.error; 2 | 3 | let consoleErrorLog: any[] = []; 4 | 5 | beforeEach(() => { 6 | consoleErrorLog = []; 7 | // Make sure we aren't triggering React console.error calls 8 | console.error = (...args: any[]) => { 9 | // NOTE: We can't throw in here directly as most console.error calls happen 10 | // inside promises and result in an unhandled promise rejection 11 | consoleErrorLog.push(`console.error called with args: ${args}`); 12 | consoleError.apply(console, args as any); 13 | }; 14 | }); 15 | 16 | afterEach(() => { 17 | if (consoleErrorLog.length > 0) { 18 | // Not using an Error object here because the stacktrace is misleading 19 | throw consoleErrorLog[0]; 20 | } 21 | 22 | console.error = consoleError; 23 | }); 24 | -------------------------------------------------------------------------------- /website/versioned_sidebars/version-1.2.0-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "version-1.2.0-docs": { 3 | "Getting Started": [ 4 | "version-1.2.0-overview", 5 | "version-1.2.0-tutorial", 6 | "version-1.2.0-resources" 7 | ], 8 | "Guides": [ 9 | "version-1.2.0-guides/validation", 10 | "version-1.2.0-guides/arrays", 11 | "version-1.2.0-guides/typescript", 12 | "version-1.2.0-guides/react-native", 13 | "version-1.2.0-guides/form-submission" 14 | ], 15 | "API Reference": [ 16 | "version-1.2.0-api/formik", 17 | "version-1.2.0-api/withFormik", 18 | "version-1.2.0-api/field", 19 | "version-1.2.0-api/fieldarray", 20 | "version-1.2.0-api/form", 21 | "version-1.2.0-api/connect", 22 | "version-1.2.0-api/fastfield" 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /website/versioned_sidebars/version-1.3.0-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "version-1.3.0-docs": { 3 | "Getting Started": [ 4 | "version-1.3.0-overview", 5 | "version-1.3.0-tutorial", 6 | "version-1.3.0-resources" 7 | ], 8 | "Guides": [ 9 | "version-1.3.0-guides/validation", 10 | "version-1.3.0-guides/arrays", 11 | "version-1.3.0-guides/typescript", 12 | "version-1.3.0-guides/react-native", 13 | "version-1.3.0-guides/form-submission" 14 | ], 15 | "API Reference": [ 16 | "version-1.3.0-api/formik", 17 | "version-1.3.0-api/withFormik", 18 | "version-1.3.0-api/field", 19 | "version-1.3.0-api/fieldarray", 20 | "version-1.3.0-api/form", 21 | "version-1.3.0-api/errormessage", 22 | "version-1.3.0-api/connect", 23 | "version-1.3.0-api/fastfield" 24 | ] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/formik/.size-snapshot.json: -------------------------------------------------------------------------------- 1 | { 2 | "./dist/formik.umd.production.js": { 3 | "bundled": 137573, 4 | "minified": 37797, 5 | "gzipped": 11769 6 | }, 7 | "./dist/formik.umd.development.js": { 8 | "bundled": 146347, 9 | "minified": 40818, 10 | "gzipped": 12952 11 | }, 12 | "./dist/formik.cjs.production.js": { 13 | "bundled": 43323, 14 | "minified": 20634, 15 | "gzipped": 5847 16 | }, 17 | "./dist/formik.cjs.development.js": { 18 | "bundled": 45484, 19 | "minified": 22585, 20 | "gzipped": 6495 21 | }, 22 | "dist/formik.esm.js": { 23 | "bundled": 41130, 24 | "minified": 21850, 25 | "gzipped": 6385, 26 | "treeshaked": { 27 | "rollup": { 28 | "code": 383, 29 | "import_statements": 349 30 | }, 31 | "webpack": { 32 | "code": 2705 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /website/static/css/fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'FormikSans'; 3 | font-weight: 400; 4 | src: url('/formik/fonts/FormikSans-Book.woff2') format('woff2'), 5 | url('/formik/fonts/FormikSans-Book.woff') format('woff'), 6 | url('/formik/fonts/FormikSans-Book.ttf') format('truetype'); 7 | } 8 | 9 | @font-face { 10 | font-family: 'FormikSans'; 11 | font-weight: 500; 12 | src: url('/formik/fonts/FormikSans-Medium.woff2') format('woff2'), 13 | url('/formik/fonts/FormikSans-Medium.woff') format('woff'), 14 | url('/formik/fonts/FormikSans-Medium.ttf') format('truetype'); 15 | } 16 | 17 | @font-face { 18 | font-family: 'FormikSans'; 19 | font-weight: 700; 20 | src: url('/formik/fonts/FormikSans-Demi.woff2') format('woff2'), 21 | url('/formik/fonts/FormikSans-Demi.woff') format('woff'), 22 | url('/formik/fonts/FormikSans-Demi.ttf') format('truetype'); 23 | } -------------------------------------------------------------------------------- /packages/formik/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src", "types"], 4 | "compilerOptions": { 5 | "target": "es5", 6 | "module": "esnext", 7 | "lib": ["dom", "esnext"], 8 | "importHelpers": true, 9 | "declaration": true, 10 | "sourceMap": true, 11 | "rootDir": "./", 12 | "strict": true, 13 | "noImplicitAny": true, 14 | "strictNullChecks": true, 15 | "strictFunctionTypes": true, 16 | "strictPropertyInitialization": true, 17 | "noImplicitThis": true, 18 | "alwaysStrict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noImplicitReturns": true, 22 | "noFallthroughCasesInSwitch": true, 23 | "moduleResolution": "node", 24 | "jsx": "react", 25 | "esModuleInterop": true, 26 | "baseUrl": "./", 27 | "paths": { 28 | "*": ["src/*", "node_modules/*"] 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/formik-native/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src", "types"], 4 | "compilerOptions": { 5 | "target": "es5", 6 | "module": "esnext", 7 | "lib": ["es2015", "es2016", "esnext"], 8 | "jsx": "react-native", 9 | "importHelpers": true, 10 | "declaration": true, 11 | "sourceMap": true, 12 | "rootDir": "./", 13 | "strict": true, 14 | "noImplicitAny": true, 15 | "strictNullChecks": true, 16 | "strictFunctionTypes": true, 17 | "strictPropertyInitialization": true, 18 | "noImplicitThis": true, 19 | "alwaysStrict": true, 20 | "noUnusedLocals": true, 21 | "noUnusedParameters": true, 22 | "noImplicitReturns": true, 23 | "noFallthroughCasesInSwitch": true, 24 | "moduleResolution": "node", 25 | "esModuleInterop": true, 26 | "baseUrl": "./", 27 | "paths": { 28 | "*": ["src/*", "node_modules/*"] 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/formik/types/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'react-testing-library'; 2 | declare module 'tiny-warning' { 3 | export default function warning(condition: any, message: string): void; 4 | } 5 | 6 | declare module 'react-lifecycles-compat' { 7 | import React from 'react'; 8 | export function polyfill

( 9 | Comp: React.ComponentType

10 | ): React.ComponentType

; 11 | } 12 | 13 | declare module 'deepmerge' { 14 | export = deepmerge; 15 | 16 | function deepmerge( 17 | x: Partial, 18 | y: Partial, 19 | options?: deepmerge.Options 20 | ): T; 21 | function deepmerge( 22 | x: T1, 23 | y: T2, 24 | options?: deepmerge.Options 25 | ): T1 & T2; 26 | 27 | namespace deepmerge { 28 | interface Options { 29 | clone?: boolean; 30 | arrayMerge?(destination: any[], source: any[], options?: Options): any[]; 31 | isMergeableObject?(value: object): boolean; 32 | } 33 | 34 | function all(objects: Array>, options?: Options): T; 35 | } 36 | } 37 | declare module 'scheduler'; 38 | -------------------------------------------------------------------------------- /website/versioned_sidebars/version-2.0.3-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "version-2.0.3-docs": { 3 | "Getting Started": [ 4 | "version-2.0.3-overview", 5 | "version-2.0.3-tutorial", 6 | "version-2.0.3-3rd-party-bindings", 7 | "version-2.0.3-migrating-v2", 8 | "version-2.0.3-resources" 9 | ], 10 | "Guides": [ 11 | "version-2.0.3-guides/validation", 12 | "version-2.0.3-guides/arrays", 13 | "version-2.0.3-guides/typescript", 14 | "version-2.0.3-guides/react-native", 15 | "version-2.0.3-guides/form-submission" 16 | ], 17 | "API Reference": [ 18 | "version-2.0.3-api/connect", 19 | "version-2.0.3-api/errormessage", 20 | "version-2.0.3-api/fastfield", 21 | "version-2.0.3-api/field", 22 | "version-2.0.3-api/fieldarray", 23 | "version-2.0.3-api/form", 24 | "version-2.0.3-api/formik", 25 | "version-2.0.3-api/useField", 26 | "version-2.0.3-api/useFormik", 27 | "version-2.0.3-api/useFormikContext", 28 | "version-2.0.3-api/withFormik" 29 | ] 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /website/versioned_sidebars/version-2.1.4-sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "version-2.1.4-docs": { 3 | "Getting Started": [ 4 | "version-2.1.4-overview", 5 | "version-2.1.4-tutorial", 6 | "version-2.1.4-migrating-v2", 7 | "version-2.1.4-3rd-party-bindings", 8 | "version-2.1.4-resources" 9 | ], 10 | "Guides": [ 11 | "version-2.1.4-guides/validation", 12 | "version-2.1.4-guides/arrays", 13 | "version-2.1.4-guides/typescript", 14 | "version-2.1.4-guides/react-native", 15 | "version-2.1.4-guides/form-submission" 16 | ], 17 | "API Reference": [ 18 | "version-2.1.4-api/connect", 19 | "version-2.1.4-api/errormessage", 20 | "version-2.1.4-api/fastfield", 21 | "version-2.1.4-api/field", 22 | "version-2.1.4-api/fieldarray", 23 | "version-2.1.4-api/form", 24 | "version-2.1.4-api/formik", 25 | "version-2.1.4-api/useField", 26 | "version-2.1.4-api/useFormik", 27 | "version-2.1.4-api/useFormikContext", 28 | "version-2.1.4-api/withFormik" 29 | ] 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/Debug.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { FormikConsumer } from 'formik'; 3 | 4 | export const Debug = () => ( 5 |

13 |
26 | Formik State 27 |
28 | 29 | {({ validationSchema, validate, onSubmit, ...rest }) => ( 30 |
37 |           {JSON.stringify(rest, null, 2)}
38 |         
39 | )} 40 |
41 |
42 | ); 43 | -------------------------------------------------------------------------------- /examples/basic/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import { Formik, Field, Form } from "formik"; 4 | 5 | const sleep = ms => new Promise(r => setTimeout(r, ms)); 6 | 7 | const Basic = () => ( 8 |
9 |

Sign Up

10 | { 17 | await sleep(500); 18 | alert(JSON.stringify(values, null, 2)); 19 | }} 20 | > 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 | ); 35 | 36 | ReactDOM.render(, document.getElementById("root")); 37 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | pull_request: 5 | types: [opened, synchronize, reopened] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | 11 | strategy: 12 | matrix: 13 | node: ['12.x'] 14 | 15 | name: Test on node ${{ matrix.node }} 16 | 17 | steps: 18 | - uses: actions/checkout@v1 19 | 20 | - name: Use Node.js ${{ matrix.node }} 21 | uses: actions/setup-node@v1 22 | with: 23 | node-version: ${{ matrix.node }} 24 | 25 | - uses: actions/cache@v1 26 | with: 27 | path: ~/.cache/yarn 28 | key: ${{ runner.os }}-yarn-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }} 29 | restore-keys: | 30 | ${{ runner.os }}-yarn- 31 | 32 | - name: Install deps, build, and test 33 | run: | 34 | node --version 35 | npm --version 36 | yarn --version 37 | yarn install --frozen-lockfile 38 | yarn test --coverage 39 | env: 40 | CI: true 41 | NODE_OPTIONS: --max-old-space-size=4096 42 | -------------------------------------------------------------------------------- /packages/formik/src/Form.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { useFormikContext } from './FormikContext'; 3 | 4 | export type FormikFormProps = Pick< 5 | React.FormHTMLAttributes, 6 | Exclude< 7 | keyof React.FormHTMLAttributes, 8 | 'onReset' | 'onSubmit' 9 | > 10 | >; 11 | 12 | type FormProps = React.ComponentPropsWithoutRef<'form'>; 13 | 14 | // @todo tests 15 | export const Form = React.forwardRef( 16 | (props: FormikFormProps, ref) => { 17 | // iOS needs an "action" attribute for nice input: https://stackoverflow.com/a/39485162/406725 18 | // We default the action to "#" in case the preventDefault fails (just updates the URL hash) 19 | const { action, ...rest } = props; 20 | const _action = action || '#'; 21 | const { handleReset, handleSubmit } = useFormikContext(); 22 | return ( 23 |
30 | ); 31 | } 32 | ); 33 | 34 | Form.displayName = 'Form'; 35 | -------------------------------------------------------------------------------- /docs/api/connect.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: connect 3 | title: connect() 4 | custom_edit_url: https://github.com/jaredpalmer/formik/edit/master/docs/api/connect.md 5 | --- 6 | 7 | `connect()` is a higher-order component (HoC) that allows you to hook anything into Formik's context. It is used internally to construct `` and ``, but you can use it to build out new components as your needs change. 8 | 9 | ## Type signature 10 | 11 | ```tsx 12 | connect(Comp: React.ComponentType }>) => React.ComponentType 13 | ``` 14 | 15 | ## Example 16 | 17 | ```jsx 18 | import React from 'react'; 19 | import { connect, getIn } from 'formik'; 20 | 21 | // This component renders an error message if a field has 22 | // an error and it's already been touched. 23 | const ErrorMessage = props => { 24 | // All FormikProps available on props.formik! 25 | const error = getIn(props.formik.errors, props.name); 26 | const touch = getIn(props.formik.touched, props.name); 27 | return touch && error ? error : null; 28 | }; 29 | 30 | export default connect(ErrorMessage); 31 | ``` 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Jared Palmer http://jaredpalmer.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/radio-group/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import { Formik, Field, Form } from "formik"; 4 | 5 | const Example = () => ( 6 |
7 |

Sign Up

8 | { 13 | await new Promise(r => setTimeout(r, 500)); 14 | alert(JSON.stringify(values, null, 2)); 15 | }} 16 | > 17 | {({ values }) => ( 18 | 19 |
Picked
20 |
21 | 25 | 29 |
Picked: {values.picked}
30 |
31 | 32 | 33 | 34 | )} 35 |
36 |
37 | ); 38 | 39 | ReactDOM.render(, document.getElementById("root")); 40 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F680Feature request" 3 | about: Suggest an idea for Formik 4 | --- 5 | 6 | ## 🚀 Feature request 7 | 8 | ### Current Behavior 9 | 10 | 11 | 12 | ### Desired Behavior 13 | 14 | 15 | 16 | ### Suggested Solution 17 | 18 | 19 | 20 | 21 | 22 | ### Who does this impact? Who is this for? 23 | 24 | 25 | 26 | ### Describe alternatives you've considered 27 | 28 | 29 | 30 | ### Additional context 31 | 32 | 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41B Bug report" 3 | about: Create a report to help make Formik better 4 | --- 5 | 6 | ## 🐛 Bug report 7 | 8 | ### Current Behavior 9 | 10 | 11 | 12 | ### Expected behavior 13 | 14 | 15 | 16 | ### Reproducible example 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | ### Suggested solution(s) 25 | 26 | 27 | 28 | ### Additional context 29 | 30 | 31 | 32 | ### Your environment 33 | 34 | 35 | 36 | | Software | Version(s) | 37 | | ---------------- | ---------- | 38 | | Formik | 39 | | React | 40 | | TypeScript | 41 | | Browser | 42 | | npm/Yarn | 43 | | Operating System | 44 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.2.0/api/connect.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: version-1.2.0-connect 3 | title: connect() 4 | custom_edit_url: https://github.com/jaredpalmer/formik/edit/master/docs/api/connect.md 5 | original_id: connect 6 | --- 7 | 8 | `connect()` is a higher-order component (HoC) that allows you to hook anything into Formik's context. It is used internally to construct `` and `
`, but you can use it to build out new components as your needs change. 9 | 10 | ## Type signature 11 | 12 | ```tsx 13 | connect(Comp: React.ComponentType>) => React.ComponentType 14 | ``` 15 | 16 | ## Example 17 | 18 | ```jsx 19 | import React from 'react'; 20 | import { connect, getIn } from 'formik'; 21 | 22 | // This component renders an error message if a field has 23 | // an error and it's already been touched. 24 | const ErrorMessage = props => { 25 | // All FormikProps available on props.formik! 26 | const error = getIn(props.formik.errors, props.name); 27 | const touch = getIn(props.formik.touched, props.name); 28 | return touch && error ? error : null; 29 | }; 30 | 31 | export default connect(ErrorMessage); 32 | ``` 33 | -------------------------------------------------------------------------------- /website/versioned_docs/version-2.0.3/api/connect.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: version-2.0.3-connect 3 | title: connect() 4 | custom_edit_url: https://github.com/jaredpalmer/formik/edit/master/docs/api/connect.md 5 | original_id: connect 6 | --- 7 | 8 | `connect()` is a higher-order component (HoC) that allows you to hook anything into Formik's context. It is used internally to construct `` and ``, but you can use it to build out new components as your needs change. 9 | 10 | ## Type signature 11 | 12 | ```tsx 13 | connect(Comp: React.ComponentType }>) => React.ComponentType 14 | ``` 15 | 16 | ## Example 17 | 18 | ```jsx 19 | import React from 'react'; 20 | import { connect, getIn } from 'formik'; 21 | 22 | // This component renders an error message if a field has 23 | // an error and it's already been touched. 24 | const ErrorMessage = props => { 25 | // All FormikProps available on props.formik! 26 | const error = getIn(props.formik.errors, props.name); 27 | const touch = getIn(props.formik.touched, props.name); 28 | return touch && error ? error : null; 29 | }; 30 | 31 | export default connect(ErrorMessage); 32 | ``` 33 | -------------------------------------------------------------------------------- /packages/formik-native/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # TSDX Bootstrap 2 | 3 | This project was bootstrapped with [TSDX](https://github.com/jaredpalmer/tsdx). 4 | 5 | ## Local Development 6 | 7 | Below is a list of commands you will probably find useful. 8 | 9 | ### `npm start` or `yarn start` 10 | 11 | Runs the project in development/watch mode. Your project will be rebuilt upon changes. TSDX has a special logger for you convenience. Error messages are pretty printed and formatted for compatibility VS Code's Problems tab. 12 | 13 | 14 | 15 | Your library will be rebuilt if you make edits. 16 | 17 | ### `npm run build` or `yarn build` 18 | 19 | Bundles the package to the `dist` folder. 20 | The package is optimized and bundled with Rollup into multiple formats (CommonJS, UMD, and ES Module). 21 | 22 | 23 | 24 | ### `npm test` or `yarn test` 25 | 26 | Runs the test watcher (Jest) in an interactive mode. 27 | By default, runs tests related to files changed since the last commit. 28 | -------------------------------------------------------------------------------- /examples/async-submission/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { Formik, Field, Form } from 'formik'; 4 | 5 | const sleep = ms => new Promise(r => setTimeout(r, ms)); 6 | 7 | const Example = () => ( 8 |
9 |

Sign Up

10 | { 17 | await sleep(500); 18 | alert(JSON.stringify(values, null, 2)); 19 | }} 20 | > 21 | {({ isSubmitting }) => ( 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 35 | 36 | )} 37 | 38 |
39 | ); 40 | 41 | ReactDOM.render(, document.getElementById('root')); 42 | -------------------------------------------------------------------------------- /examples/SyncValidation.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Formik, Field, Form, ErrorMessage } from 'formik'; 3 | import { Debug } from './Debug'; 4 | 5 | const validate = values => { 6 | const errors = {}; 7 | if (!values.email) { 8 | errors.email = 'Required'; 9 | } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) { 10 | errors.email = 'Invalid email address'; 11 | } 12 | return errors; 13 | }; 14 | 15 | const SignIn = () => ( 16 |
17 |

Sign In

18 | { 25 | setTimeout(() => { 26 | alert(JSON.stringify(values, null, 2)); 27 | }, 500); 28 | }} 29 | render={({ errors, touched }) => ( 30 |
31 | 32 | 33 |
34 | 35 |
36 | 37 | 38 | 39 | 40 | 41 | )} 42 | /> 43 |
44 | ); 45 | 46 | export default SignIn; 47 | -------------------------------------------------------------------------------- /examples/AsyncValidation.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Formik, Field, Form, ErrorMessage } from 'formik'; 3 | import { Debug } from './Debug'; 4 | 5 | // Async Validation 6 | const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); 7 | 8 | const validate = (values) => { 9 | return sleep(300).then(() => { 10 | const errors = {}; 11 | 12 | if (['admin', 'null', 'god'].includes(values.username)) { 13 | errors.username = 'Nice try'; 14 | } 15 | 16 | if (!values.username) { 17 | errors.username = 'Required'; 18 | } 19 | 20 | if (Object.keys(errors).length) { 21 | throw errors; 22 | } 23 | }); 24 | }; 25 | 26 | const Username = () => ( 27 |
28 |

Pick a username

29 | { 35 | sleep(500).then(() => { 36 | alert(JSON.stringify(values, null, 2)); 37 | }); 38 | }} 39 | render={({ errors, touched }) => ( 40 |
41 | 42 | 43 | 44 | 45 | 46 | 47 | )} 48 | /> 49 |
50 | ); 51 | 52 | export default Username; 53 | -------------------------------------------------------------------------------- /website/static/img/formik-mark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /website/static/img/logos/gremlin.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/basic-typescript/index.tsx: -------------------------------------------------------------------------------- 1 | import 'react-app-polyfill/ie11'; 2 | import * as React from 'react'; 3 | import * as ReactDOM from 'react-dom'; 4 | import { Formik, Field, Form, FormikHelpers } from 'formik'; 5 | 6 | interface Values { 7 | firstName: string; 8 | lastName: string; 9 | email: string; 10 | } 11 | 12 | const App = () => { 13 | return ( 14 |
15 |

Signup

16 | 25 | ) => { 26 | setTimeout(() => { 27 | alert(JSON.stringify(values, null, 2)); 28 | setSubmitting(false); 29 | }, 500); 30 | }} 31 | > 32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 46 | 47 | 48 | 49 |
50 |
51 | ); 52 | }; 53 | 54 | ReactDOM.render(, document.getElementById('root')); 55 | -------------------------------------------------------------------------------- /packages/formik/test/types.test.tsx: -------------------------------------------------------------------------------- 1 | import { FormikTouched, FormikErrors } from '../src'; 2 | 3 | describe('Formik Types', () => { 4 | describe('FormikTouched', () => { 5 | type Values = { 6 | id: string; 7 | social: { 8 | facebook: string; 9 | }; 10 | }; 11 | 12 | it('it should infer nested object structure of touched property from Values', () => { 13 | const touched: FormikTouched = { 14 | id: true, 15 | social: { facebook: true }, 16 | }; 17 | // type touched = { 18 | // id?: boolean | undefined; 19 | // social?: { 20 | // facebook?: boolean | undefined; 21 | // } | undefined; 22 | // } 23 | const id: boolean | undefined = touched.id; 24 | expect(id).toBe(true); 25 | const facebook: boolean | undefined = touched.social!.facebook; 26 | expect(facebook).toBe(true); 27 | }); 28 | 29 | it('it should infer nested object structure of error property from Values', () => { 30 | const errors: FormikErrors = { 31 | id: 'error', 32 | social: { facebook: 'error' }, 33 | }; 34 | // type touched = { 35 | // id?: {} | undefined; 36 | // social?: { 37 | // facebook?: {} | undefined; 38 | // } | undefined; 39 | // } 40 | const id: {} | undefined = errors.id; 41 | expect(id).toBe('error'); 42 | const facebook: {} | undefined = errors.social!.facebook; 43 | expect(facebook).toBe('error'); 44 | }); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /examples/withFormik.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import * as Yup from 'yup'; 3 | import { withFormik } from '../src/formik'; 4 | import { Debug } from './Debug'; 5 | 6 | const formikEnhancer = withFormik({ 7 | mapPropsToValues: props => ({ email: props.user.email }), 8 | validationSchema: Yup.object().shape({ 9 | email: Yup.string() 10 | .email('Invalid email address') 11 | .required('Email is required!'), 12 | }), 13 | handleSubmit: (values, { setSubmitting }) => { 14 | setTimeout(() => { 15 | alert(JSON.stringify(values, null, 2)); 16 | setSubmitting(false); 17 | }, 1000); 18 | }, 19 | displayName: 'MyForm', // helps with React DevTools 20 | }); 21 | 22 | const MyForm = props => { 23 | const { 24 | values, 25 | touched, 26 | errors, 27 | dirty, 28 | isSubmitting, 29 | handleChange, 30 | handleBlur, 31 | handleSubmit, 32 | handleReset, 33 | } = props; 34 | return ( 35 |
36 | 37 | 38 |
39 | 40 |
41 | 49 | 52 | 53 | 54 | ); 55 | }; 56 | 57 | export default formikEnhancer(MyForm); 58 | -------------------------------------------------------------------------------- /packages/formik/test/ErrorMessage.test.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import * as ReactDOM from 'react-dom'; 3 | import { Formik, FormikProps, ErrorMessage } from '../src'; 4 | import { noop } from './testHelpers'; 5 | 6 | interface TestFormValues { 7 | name: string; 8 | email: string; 9 | } 10 | 11 | const TestForm: React.SFC = p => ( 12 | 17 | ); 18 | 19 | describe('', () => { 20 | const node = document.createElement('div'); 21 | afterEach(() => { 22 | ReactDOM.unmountComponentAtNode(node); 23 | }); 24 | it('renders with children as a function', async () => { 25 | let actual: any; /** ErrorMessage ;) */ 26 | let actualFProps: any; 27 | let message = 'Wrong'; 28 | ReactDOM.render( 29 | ) => { 31 | actualFProps = fProps; 32 | return ( 33 |
34 | 35 | {props => (actual = props) ||
{props}
} 36 |
37 |
38 | ); 39 | }} 40 | />, 41 | node 42 | ); 43 | 44 | actualFProps.setFieldError('email', message); 45 | // Only renders if Field has been visited. 46 | expect(actual).toEqual(undefined); 47 | actualFProps.setFieldTouched('email'); 48 | // Renders after being visited with an error. 49 | expect(actual).toEqual(message); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | name: Build, test, Publish 12 | steps: 13 | - uses: actions/checkout@v1 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: 12 17 | - run: yarn install --frozen-lockfile 18 | - run: yarn test 19 | env: 20 | CI: true 21 | - name: Potentially save npm token 22 | run: | 23 | ([[ ! -z ${{ secrets.NPM_TOKEN }} ]] && echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" >> ~/.npmrc) || echo "Did not write npm token" 24 | - name: Potentially publish canary to npm 25 | run: | 26 | if \ 27 | ls ~/.npmrc >/dev/null 2>&1 && \ 28 | [[ $(git describe --exact-match 2> /dev/null || :) =~ -canary ]]; \ 29 | then 30 | yarn run lerna publish from-git --npm-tag canary --yes 31 | else 32 | echo "Did not publish canary" 33 | fi 34 | env: 35 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 36 | - name: Potentially publish stable to npm 37 | run: | 38 | if \ 39 | ls ~/.npmrc >/dev/null 2>&1 && \ 40 | [[ ! $(git describe --exact-match 2> /dev/null || :) =~ -canary ]]; \ 41 | then 42 | yarn run lerna publish from-git --yes 43 | else 44 | echo "Did not publish" 45 | fi 46 | env: 47 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 48 | -------------------------------------------------------------------------------- /packages/formik-native/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "formik-native", 3 | "version": "2.1.4", 4 | "license": "MIT", 5 | "author": "Jared Palmer ", 6 | "repository": "jaredpalmer/formik", 7 | "keywords": [ 8 | "formik", 9 | "react", 10 | "react-native", 11 | "form", 12 | "validation", 13 | "forms", 14 | "higher order component", 15 | "hoc", 16 | "hooks" 17 | ], 18 | "main": "dist/index.js", 19 | "module": "dist/index.esm.js", 20 | "react-native": "src/index.js", 21 | "typings": "dist/index.d.ts", 22 | "files": [ 23 | "dist" 24 | ], 25 | "scripts": { 26 | "start": "tsdx watch --verbose", 27 | "build": "tsdx build", 28 | "test": "tsdx test", 29 | "lint": "tsdx lint", 30 | "prepublish": "npm run build" 31 | }, 32 | "peerDependencies": { 33 | "react": ">=16.3.0" 34 | }, 35 | "husky": { 36 | "hooks": { 37 | "pre-commit": "tsdx lint" 38 | } 39 | }, 40 | "prettier": { 41 | "printWidth": 80, 42 | "semi": true, 43 | "singleQuote": true, 44 | "trailingComma": "es5" 45 | }, 46 | "dependencies": { 47 | "formik": "2.1.4" 48 | }, 49 | "devDependencies": { 50 | "@react-native-community/eslint-config": "^0.0.5", 51 | "@semantic-release/changelog": "^3.0.5", 52 | "@types/jest": "^24.0.23", 53 | "@types/react": "^16.8.23", 54 | "@types/react-native": "^0.57.65", 55 | "husky": "^3.1.0", 56 | "react": "^16.8.6", 57 | "react-native": "https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz", 58 | "tsdx": "^0.11.0", 59 | "tslib": "^1.10.0", 60 | "typescript": "^3.7.3" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /examples/FastField.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Formik, FastField, Form } from 'formik'; 3 | import { Debug } from './Debug'; 4 | 5 | class Input extends React.Component { 6 | renders = 0; 7 | render() { 8 | return ( 9 |
10 | 11 |

# of renders: {this.renders++}

12 |
13 | ); 14 | } 15 | } 16 | 17 | const Basic = () => ( 18 |
19 |

Sign Up

20 | { 27 | setTimeout(() => { 28 | setSubmitting(false); 29 | 30 | alert(JSON.stringify(values, null, 2)); 31 | }, 500); 32 | }} 33 | render={({ isSubmitting }) => ( 34 |
35 | 36 | 42 | 43 | 44 | 50 | 51 | 52 | 59 | 60 | 61 | 62 | 63 | )} 64 | /> 65 |
66 | ); 67 | 68 | export default Basic; 69 | -------------------------------------------------------------------------------- /packages/formik/src/connect.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import hoistNonReactStatics from 'hoist-non-react-statics'; 3 | 4 | import { FormikContextType } from './types'; 5 | import { FormikConsumer } from './FormikContext'; 6 | import invariant from 'tiny-warning'; 7 | 8 | /** 9 | * Connect any component to Formik context, and inject as a prop called `formik`; 10 | * @param Comp React Component 11 | */ 12 | export function connect( 13 | Comp: React.ComponentType }> 14 | ) { 15 | const C: React.SFC = (props: OuterProps) => ( 16 | 17 | {formik => { 18 | invariant( 19 | !!formik, 20 | `Formik context is undefined, please verify you are rendering
, , , , or your custom context-using component as a child of a component. Component name: ${Comp.name}` 21 | ); 22 | return ; 23 | }} 24 | 25 | ); 26 | const componentDisplayName = 27 | Comp.displayName || 28 | Comp.name || 29 | (Comp.constructor && Comp.constructor.name) || 30 | 'Component'; 31 | 32 | // Assign Comp to C.WrappedComponent so we can access the inner component in tests 33 | // For example, gets us 34 | (C as React.SFC & { 35 | WrappedComponent: React.ReactNode; 36 | }).WrappedComponent = Comp; 37 | 38 | C.displayName = `FormikConnect(${componentDisplayName})`; 39 | 40 | return hoistNonReactStatics( 41 | C, 42 | Comp as React.ComponentClass< 43 | OuterProps & { formik: FormikContextType } 44 | > // cast type to ComponentClass (even if SFC) 45 | ) as React.ComponentType; 46 | } 47 | -------------------------------------------------------------------------------- /packages/formik/src/ErrorMessage.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { FormikContextType } from './types'; 3 | import { getIn, isFunction } from './utils'; 4 | import { connect } from './connect'; 5 | 6 | export interface ErrorMessageProps { 7 | name: string; 8 | className?: string; 9 | component?: string | React.ComponentType; 10 | children?: (errorMessage: string) => React.ReactNode; 11 | render?: (errorMessage: string) => React.ReactNode; 12 | } 13 | 14 | class ErrorMessageImpl extends React.Component< 15 | ErrorMessageProps & { formik: FormikContextType } 16 | > { 17 | shouldComponentUpdate( 18 | props: ErrorMessageProps & { formik: FormikContextType } 19 | ) { 20 | if ( 21 | getIn(this.props.formik.errors, this.props.name) !== 22 | getIn(props.formik.errors, this.props.name) || 23 | getIn(this.props.formik.touched, this.props.name) !== 24 | getIn(props.formik.touched, this.props.name) || 25 | Object.keys(this.props).length !== Object.keys(props).length 26 | ) { 27 | return true; 28 | } else { 29 | return false; 30 | } 31 | } 32 | 33 | render() { 34 | let { component, formik, render, children, name, ...rest } = this.props; 35 | 36 | const touch = getIn(formik.touched, name); 37 | const error = getIn(formik.errors, name); 38 | 39 | return !!touch && !!error 40 | ? render 41 | ? isFunction(render) 42 | ? render(error) 43 | : null 44 | : children 45 | ? isFunction(children) 46 | ? children(error) 47 | : null 48 | : component 49 | ? React.createElement(component, rest as any, error) 50 | : error 51 | : null; 52 | } 53 | } 54 | 55 | export const ErrorMessage = connect< 56 | ErrorMessageProps, 57 | ErrorMessageProps & { formik: FormikContextType } 58 | >(ErrorMessageImpl); 59 | -------------------------------------------------------------------------------- /website/static/img/logos/viacom.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /website/pages/en/users.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-present Jared Palmer. 3 | * This source code is licensed under the MIT license found in the 4 | * LICENSE file in the root directory of this source tree. 5 | * @format 6 | */ 7 | 8 | const React = require('react'); 9 | 10 | const CompLibrary = require('../../core/CompLibrary.js'); 11 | 12 | const Container = CompLibrary.Container; 13 | 14 | const siteConfig = require(`${process.cwd()}/siteConfig.js`); 15 | 16 | class Users extends React.Component { 17 | render() { 18 | if ((siteConfig.users || []).length === 0) { 19 | return null; 20 | } 21 | 22 | const editUrl = `${siteConfig.repoUrl}/edit/master/website/siteConfig.js`; 23 | const showcase = siteConfig.users.map(user => ( 24 | 25 | {user.caption} 31 | 32 | )); 33 | 34 | return ( 35 |
36 | 37 |
38 |
39 |

Who's using Formik?

40 |

41 | Formik has been powering forms at{' '} 42 | The Palmer Group since 2016. 43 | Formik was open sourced in 2017 and is used by teams of all 44 | sizes. 45 |

46 |
47 |
{showcase}
48 |

Are you using Formik?

49 | 50 | Add your company 51 | 52 |
53 |
54 |
55 | ); 56 | } 57 | } 58 | 59 | Users.title = 'Users'; 60 | Users.description = 'Companies and Projects Using Formik in Production.'; 61 | module.exports = Users; 62 | -------------------------------------------------------------------------------- /examples/checkboxes/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import { Formik, Field, Form } from "formik"; 4 | 5 | const sleep = ms => new Promise(r => setTimeout(r, ms)); 6 | 7 | const Basic = () => ( 8 |
9 |

Sign Up

10 | { 16 | await sleep(500); 17 | alert(JSON.stringify(values, null, 2)); 18 | }} 19 | > 20 | {({ values }) => ( 21 | 22 | {/* 23 | This first checkbox will result in a boolean value being stored. Note that the `value` prop 24 | on the is omitted 25 | */} 26 | 30 | 31 | {/* 32 | Multiple checkboxes with the same name attribute, but different 33 | value attributes will be considered a "checkbox group". Formik will automagically 34 | bind the checked values to a single array for your benefit. All the add and remove 35 | logic will be taken care of for you. 36 | */} 37 |
Checked
38 |
39 | 43 | 47 | 51 |
52 | 53 | 54 | 55 | )} 56 |
57 |
58 | ); 59 | 60 | ReactDOM.render(, document.getElementById("root")); 61 | -------------------------------------------------------------------------------- /docs/guides/react-native.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: react-native 3 | title: React Native 4 | custom_edit_url: https://github.com/jaredpalmer/formik/edit/master/docs/guides/react-native.md 5 | --- 6 | 7 | **Formik is 100% compatible with React Native and React Native Web.** However, 8 | because of differences between ReactDOM's and React Native's handling of forms 9 | and text input, there are some differences to be aware of. This section will walk 10 | you through them and what we consider to be best practices. 11 | 12 | ### The gist 13 | 14 | Before going any further, here's a super minimal gist of how to use Formik with 15 | React Native that demonstrates the key differences: 16 | 17 | ```jsx 18 | // Formik x React Native example 19 | import React from 'react'; 20 | import { Button, TextInput, View } from 'react-native'; 21 | import { Formik } from 'formik'; 22 | 23 | export const MyReactNativeForm = props => ( 24 | console.log(values)} 27 | > 28 | {({ handleChange, handleBlur, handleSubmit, values }) => ( 29 | 30 | 35 | 36 | 37 | 38 | ); 39 | ``` 40 | 41 | ## Arrays 42 | 43 | Formik also has support for arrays and arrays of objects out of the box. Using lodash-like bracket syntax for `name` string you can quickly build fields for items in a list. 44 | 45 | ```jsx 46 | import React from 'react'; 47 | import { Formik, Form, Field } from 'formik'; 48 | 49 | export const BasicArrayExample = () => ( 50 |
51 |

Friends

52 | { 57 | // same shape as initial values 58 | console.log(values); 59 | }} 60 | > 61 | 62 | 63 | 64 | 65 |
66 | ); 67 | ``` 68 | 69 | For more information around manipulating (add/remove/etc) items in lists, see the API reference section on the `` component. 70 | -------------------------------------------------------------------------------- /website/pages/en/help.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-present Jared Palmer. 3 | * This source code is licensed under the MIT license found in the 4 | * LICENSE file in the root directory of this source tree. 5 | * @format 6 | */ 7 | 8 | const React = require('react'); 9 | 10 | const CompLibrary = require('../../core/CompLibrary.js'); 11 | 12 | const Container = CompLibrary.Container; 13 | const GridBlock = CompLibrary.GridBlock; 14 | 15 | const siteConfig = require(`${process.cwd()}/siteConfig.js`); 16 | 17 | function docUrl(doc, language) { 18 | return `${siteConfig.baseUrl}docs/${ 19 | language && language !== 'en' ? `${language}/` : '' 20 | }${doc}`; 21 | } 22 | 23 | class Help extends React.Component { 24 | render() { 25 | const language = this.props.language || ''; 26 | const supportLinks = [ 27 | { 28 | content: `Learn more using the [documentation on this site.](${docUrl( 29 | 'overview.html', 30 | language 31 | )})`, 32 | title: 'Browse Docs', 33 | }, 34 | { 35 | content: 36 | 'Ask questions about the documentation and project on [Spectrum.chat](https://spectrum.chat/palmer) or [Reactiflux Discord](https://discord.gg/cU6MCve)', 37 | title: 'Join the community', 38 | }, 39 | { 40 | content: 41 | "Find out what's new with this project. Follow [@jaredpalmer](https://twitter.com/jaredpalmer) and [@eonwhite](https://twitter.com/eonwhite) on Twitter", 42 | title: 'Stay up to date', 43 | }, 44 | ]; 45 | 46 | return ( 47 |
48 | 49 |
50 |
51 |

Need help?

52 |
53 |

This project is maintained by a dedicated group of people.

54 | 55 |
56 |
57 |
58 | ); 59 | } 60 | } 61 | Help.title = 'Help'; 62 | Help.description = 'Get Help with Formik.'; 63 | module.exports = Help; 64 | -------------------------------------------------------------------------------- /dist/Field.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { FormikProps, GenericFieldHTMLAttributes, FieldMetaProps, FieldHelperProps, FieldInputProps, FieldValidator } from './types'; 3 | export interface FieldProps { 4 | field: FieldInputProps; 5 | form: FormikProps; 6 | meta: FieldMetaProps; 7 | } 8 | export interface FieldConfig { 9 | /** 10 | * Field component to render. Can either be a string like 'select' or a component. 11 | */ 12 | component?: string | React.ComponentType> | React.ComponentType | React.ForwardRefExoticComponent; 13 | /** 14 | * Component to render. Can either be a string e.g. 'select', 'input', or 'textarea', or a component. 15 | */ 16 | as?: React.ComponentType['field']> | string | React.ComponentType | React.ForwardRefExoticComponent; 17 | /** 18 | * Render prop (works like React router's } />) 19 | * @deprecated 20 | */ 21 | render?: (props: FieldProps) => React.ReactNode; 22 | /** 23 | * Children render function {props => ...}) 24 | */ 25 | children?: ((props: FieldProps) => React.ReactNode) | React.ReactNode; 26 | /** 27 | * Validate a single field value independently 28 | */ 29 | validate?: FieldValidator; 30 | /** 31 | * Field name 32 | */ 33 | name: string; 34 | /** HTML input type */ 35 | type?: string; 36 | /** Field value */ 37 | value?: any; 38 | /** Inner ref */ 39 | innerRef?: (instance: any) => void; 40 | } 41 | export declare type FieldAttributes = GenericFieldHTMLAttributes & FieldConfig & T & { 42 | name: string; 43 | }; 44 | export declare type FieldHookConfig = GenericFieldHTMLAttributes & FieldConfig; 45 | export declare function useField(propsOrFieldName: string | FieldHookConfig): [FieldInputProps, FieldMetaProps, FieldHelperProps]; 46 | export declare function Field({ validate, name, render, children, as: is, // `as` is reserved in typescript lol 47 | component, ...props }: FieldAttributes): any; 48 | -------------------------------------------------------------------------------- /docs/guides/form-submission.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: form-submission 3 | title: Form Submission 4 | custom_edit_url: https://github.com/jaredpalmer/formik/edit/master/docs/guides/form-submission.md 5 | --- 6 | 7 | ## Submission Phases 8 | 9 | To submit a form in Formik, you need to somehow fire off the provided `handleSubmit(e)` or `submitForm` prop. When you call either of these methods, Formik will execute the following _(pseudo code)_ each time: 10 | 11 | ### Pre-submit 12 | 13 | - Touch all fields. `initialValues` are required and should always be specified. See [#445](https://github.com/jaredpalmer/formik/issues/445#issuecomment-366952762) 14 | - Set `isSubmitting` to `true` 15 | - Increment `submitCount` + 1 16 | 17 | ### Validation 18 | 19 | - Set `isValidating` to `true` 20 | - Run all field-level validations, `validate`, and `validationSchema` asynchronously and deeply merge results 21 | - Are there any errors? 22 | - Yes: Abort submission. Set `isValidating` to `false`, set `errors`, set `isSubmitting` to `false` 23 | - No: Set `isValidating` to `false`, proceed to "Submission" 24 | 25 | ### Submission 26 | 27 | - Proceed with running your submission handler (i.e.`onSubmit` or `handleSubmit`) 28 | - _you call `setSubmitting(false)`_ in your handler to finish the cycle 29 | 30 | ## Frequently Asked Questions 31 | 32 |
33 | How do I determine if my submission handler is executing? 34 | 35 | If `isValidating` is `false` and `isSubmitting` is `true`. 36 | 37 |
38 | 39 |
40 | Why does Formik touch all fields before submit? 41 | 42 | It is common practice to only show an input's errors in the UI if it has been visited (a.k.a "touched"). Before submitting a form, Formik touches all fields so that all errors that may have been hidden will now be visible. 43 | 44 |
45 | 46 |
47 | How do I protect against double submits? 48 | 49 | Disable whatever is triggering submission if `isSubmitting` is `true`. 50 | 51 |
52 | 53 |
54 | How do I know when my form is validating before submit? 55 | 56 | If `isValidating` is `true` and `isSubmitting` is `true`. 57 | 58 |
59 | -------------------------------------------------------------------------------- /examples/DebouncedAutoSave.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useFormikContext, Formik, Field, Form } from 'formik'; 3 | import { Debug } from './Debug'; 4 | import debounce from 'just-debounce-it'; 5 | 6 | const AutoSave = ({ debounceMs }) => { 7 | const formik = useFormikContext(); 8 | const [lastSaved, setLastSaved] = React.useState(null); 9 | const debouncedSubmit = React.useCallback( 10 | debounce( 11 | () => 12 | formik.submitForm().then(() => setLastSaved(new Date().toISOString())), 13 | debounceMs 14 | ), 15 | [debounceMs, formik.submitForm] 16 | ); 17 | 18 | React.useEffect(() => { 19 | debouncedSubmit(); 20 | }, [debouncedSubmit, formik.values]); 21 | 22 | return ( 23 | <> 24 | {!!formik.isSubmitting 25 | ? 'saving...' 26 | : lastSaved !== null 27 | ? `Last Saved: ${lastSaved}` 28 | : null} 29 | 30 | ); 31 | }; 32 | 33 | const AutoSavingForm = () => ( 34 |
35 | { 42 | return new Promise(resolve => 43 | setTimeout(() => { 44 | console.log('submitted', JSON.stringify(values, null, 2)); 45 | setSubmitting(false); 46 | resolve(); 47 | }, 1000) 48 | ); 49 | }} 50 | render={() => ( 51 | 52 |

53 | AutoSavingForm{' '} 54 | 55 | 56 | 57 |

58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | )} 72 | /> 73 |
74 | ); 75 | 76 | export default AutoSavingForm; 77 | -------------------------------------------------------------------------------- /website/versioned_docs/version-2.0.3/guides/arrays.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: version-2.0.3-arrays 3 | title: Arrays and Nested Objects 4 | custom_edit_url: https://github.com/jaredpalmer/formik/edit/master/docs/guides/arrays.md 5 | original_id: arrays 6 | --- 7 | 8 | Formik has support for nested objects and arrays out of the box. These 2 subjects are somewhat related because they both leverage the same syntax. 9 | 10 | ## Nested Objects 11 | 12 | The `name` props in Formik can use lodash-like dot paths to reference nested Formik values. This means that you do not need to flatten out your form's values anymore. 13 | 14 | ```jsx 15 | import React from 'react'; 16 | import { Formik, Form, Field } from 'formik'; 17 | 18 | export const NestedExample = () => ( 19 |
20 |

Social Profiles

21 | { 29 | // same shape as initial values 30 | console.log(values); 31 | }} 32 | > 33 |
34 | 35 | 36 | 37 | 38 |
39 |
40 | ); 41 | ``` 42 | 43 | ## Arrays 44 | 45 | Formik also has support for arrays and arrays of objects out of the box. Using lodash-like bracket syntax for `name` string you can quickly build fields for items in a list. 46 | 47 | ```jsx 48 | import React from 'react'; 49 | import { Formik, Form, Field } from 'formik'; 50 | 51 | export const BasicArrayExample = () => ( 52 |
53 |

Friends

54 | { 59 | // same shape as initial values 60 | console.log(values); 61 | }} 62 | > 63 |
64 | 65 | 66 | 67 | 68 |
69 |
70 | ); 71 | ``` 72 | 73 | For more information around manipulating (add/remove/etc) items in lists, see the API reference section on the `` component. 74 | -------------------------------------------------------------------------------- /website/static/img/logos/sony.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /website/versioned_docs/version-1.5.0/guides/form-submission.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: version-1.5.0-form-submission 3 | title: Form Submission 4 | custom_edit_url: https://github.com/jaredpalmer/formik/edit/master/docs/guides/form-submission.md 5 | original_id: form-submission 6 | --- 7 | 8 | ## Submission Phases 9 | 10 | To submit a form in Formik, you need to somehow fire off the provided `handleSubmit(e)` or `submitForm` prop. When you call either of these methods, Formik will execute the following _(pseudo code)_ each time: 11 | 12 | ### Pre-submit 13 | 14 | * Touch all fields. `initialValues` are required and should always be specified. See [#445](https://github.com/jaredpalmer/formik/issues/445#issuecomment-366952762) 15 | * Set `isSubmitting` to `true` 16 | * Increment `submitCount` + 1 17 | 18 | ### Validation 19 | 20 | * Set `isValidating` to `true` 21 | * Run all field-level validations, `validate`, and `validationSchema` asynchronously and deeply merge results 22 | * Are there any errors? 23 | * Yes: Abort submission. Set `isValidating` to `false`, set `errors`, set `isSubmitting` to `false` 24 | * No: Set `isValidating` to `false`, proceed to "Submission" 25 | 26 | ### Submission 27 | 28 | * Proceed with running your submission handler (i.e.`onSubmit` or `handleSubmit`) 29 | * _you call `setSubmitting(false)`_ in your handler to finish the cycle 30 | 31 | ## Frequently Asked Questions 32 | 33 |
34 | How do I determine if my submission handler is executing? 35 | 36 | If `isValidating` is `false` and `isSubmitting` is `true`. 37 | 38 |
39 | 40 |
41 | Why does Formik touch all fields before submit? 42 | 43 | It is common practice to only show an input's errors in the UI if it has been visited (a.k.a "touched"). Before submitting a form, Formik touches all fields so that all errors that may have been hidden will now be visible. 44 | 45 |
46 | 47 |
48 | How do I protect against double submits? 49 | 50 | Disable whatever is triggering submission if `isSubmitting` is `true`. 51 | 52 |
53 | 54 |
55 | How do I know when my form is validating before submit? 56 | 57 | If `isValidating` is `true` and `isSubmitting` is `true`. 58 | 59 |
60 | -------------------------------------------------------------------------------- /website/versioned_docs/version-2.0.3/guides/form-submission.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: version-2.0.3-form-submission 3 | title: Form Submission 4 | custom_edit_url: https://github.com/jaredpalmer/formik/edit/master/docs/guides/form-submission.md 5 | original_id: form-submission 6 | --- 7 | 8 | ## Submission Phases 9 | 10 | To submit a form in Formik, you need to somehow fire off the provided `handleSubmit(e)` or `submitForm` prop. When you call either of these methods, Formik will execute the following _(pseudo code)_ each time: 11 | 12 | ### Pre-submit 13 | 14 | - Touch all fields. `initialValues` are required and should always be specified. See [#445](https://github.com/jaredpalmer/formik/issues/445#issuecomment-366952762) 15 | - Set `isSubmitting` to `true` 16 | - Increment `submitCount` + 1 17 | 18 | ### Validation 19 | 20 | - Set `isValidating` to `true` 21 | - Run all field-level validations, `validate`, and `validationSchema` asynchronously and deeply merge results 22 | - Are there any errors? 23 | - Yes: Abort submission. Set `isValidating` to `false`, set `errors`, set `isSubmitting` to `false` 24 | - No: Set `isValidating` to `false`, proceed to "Submission" 25 | 26 | ### Submission 27 | 28 | - Proceed with running your submission handler (i.e.`onSubmit` or `handleSubmit`) 29 | - _you call `setSubmitting(false)`_ in your handler to finish the cycle 30 | 31 | ## Frequently Asked Questions 32 | 33 |
34 | How do I determine if my submission handler is executing? 35 | 36 | If `isValidating` is `false` and `isSubmitting` is `true`. 37 | 38 |
39 | 40 |
41 | Why does Formik touch all fields before submit? 42 | 43 | It is common practice to only show an input's errors in the UI if it has been visited (a.k.a "touched"). Before submitting a form, Formik touches all fields so that all errors that may have been hidden will now be visible. 44 | 45 |
46 | 47 |
48 | How do I protect against double submits? 49 | 50 | Disable whatever is triggering submission if `isSubmitting` is `true`. 51 | 52 |
53 | 54 |
55 | How do I know when my form is validating before submit? 56 | 57 | If `isValidating` is `true` and `isSubmitting` is `true`. 58 | 59 |
60 | -------------------------------------------------------------------------------- /website/static/img/logos/nokia.svg: -------------------------------------------------------------------------------- 1 | Nokia_wordmarkCreated with Sketch. -------------------------------------------------------------------------------- /website/static/js/code-blocks-buttons.js: -------------------------------------------------------------------------------- 1 | // Copied from Docusaurus websit 2 | // @see https://github.com/facebook/Docusaurus/blob/master/website/static/js/code-blocks-buttons.js 3 | // Turn off ESLint for this file because it's sent down to users as-is. 4 | /* eslint-disable */ 5 | window.addEventListener('load', function() { 6 | function button(label, ariaLabel, icon, className) { 7 | const btn = document.createElement('button'); 8 | btn.classList.add('btnIcon', className); 9 | btn.setAttribute('type', 'button'); 10 | btn.setAttribute('aria-label', ariaLabel); 11 | btn.innerHTML = 12 | '
' + 13 | icon + 14 | '' + 15 | label + 16 | '' + 17 | '
'; 18 | return btn; 19 | } 20 | 21 | function addButtons(codeBlockSelector, btn) { 22 | document.querySelectorAll(codeBlockSelector).forEach(function(code) { 23 | code.parentNode.appendChild(btn.cloneNode(true)); 24 | }); 25 | } 26 | 27 | const copyIcon = 28 | ''; 29 | 30 | addButtons( 31 | '.hljs', 32 | button('Copy', 'Copy code to clipboard', copyIcon, 'btnClipboard') 33 | ); 34 | 35 | const clipboard = new ClipboardJS('.btnClipboard', { 36 | target: function(trigger) { 37 | return trigger.parentNode.querySelector('code'); 38 | }, 39 | }); 40 | 41 | clipboard.on('success', function(event) { 42 | event.clearSelection(); 43 | const textEl = event.trigger.querySelector('.btnIcon__label'); 44 | textEl.textContent = 'Copied'; 45 | setTimeout(function() { 46 | textEl.textContent = 'Copy'; 47 | }, 2000); 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /docs/api/useFormikContext.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: useFormikContext 3 | title: useFormikContext() 4 | custom_edit_url: https://github.com/jaredpalmer/formik/edit/master/docs/api/useFormikContext.md 5 | --- 6 | 7 | `useFormikContext()` is a custom React hook that will return all Formik state and helpers via [React Context](https://reactjs.org/docs/context.html). 8 | 9 | ## Example 10 | 11 | Here's an example of a form that works similarly to Stripe's 2-factor verification form. As soon as you type a 6 digit number, the form will automatically submit (i.e. no enter keypress is needed). 12 | 13 | ```js 14 | import React from 'react'; 15 | import { useFormikContext, Formik, Form, Field } from 'formik'; 16 | 17 | const AutoSubmitToken = () => { 18 | // Grab values and submitForm from context 19 | const { values, submitForm } = useFormikContext(); 20 | React.useEffect(() => { 21 | // Submit the form imperatively as an effect as soon as form values.token are 6 digits long 22 | if (values.token.length === 6) { 23 | submitForm(); 24 | } 25 | }, [values, submitForm]); 26 | return null; 27 | }; 28 | 29 | const TwoFactorVerificationForm = () => ( 30 |
31 |

2-step Verification

32 |

Please enter the 6 digit code sent to your device

33 | { 36 | const errors = {}; 37 | if (values.token.length < 5) { 38 | errors.token = 'Invalid code. Too short.' 39 | } 40 | return errors 41 | }} 42 | onSubmit={(values, actions) => { 43 | setTimeout(() => { 44 | alert(JSON.stringify(values, null, 2)); 45 | actions.setSubmitting(false); 46 | }, 1000); 47 | }} 48 | > 49 |
50 | 51 | 52 | 53 |
54 |
55 | ); 56 | ``` 57 | 58 | --- 59 | 60 | # Reference 61 | 62 | ## `useFormikContext(): FormikProps` 63 | 64 | A custom React Hook that returns Formik states and helpers via React Context. Thus, this hook will only work if there is a parent Formik React Context from which it can pull from. If called without a parent context (i.e. a descendent of a `` component or `withFormik` higher-order component), you will get a warning in your console. 65 | -------------------------------------------------------------------------------- /website/versioned_docs/version-2.0.3/api/useFormikContext.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: version-2.0.3-useFormikContext 3 | title: useFormikContext() 4 | custom_edit_url: https://github.com/jaredpalmer/formik/edit/master/docs/api/useFormikContext.md 5 | original_id: useFormikContext 6 | --- 7 | 8 | `useFormikContext()` is a custom React hook that will return all Formik state and helpers via [React Context](https://reactjs.org/docs/context.html). 9 | 10 | ## Example 11 | 12 | Here's an example of a form that works similarly to Stripe's 2-factor verification form. As soon as you type a 6 digit number, the form will automatically submit (i.e. no enter keypress is needed). 13 | 14 | ```js 15 | import React from 'react'; 16 | import { useFormikContext, Formik, Form, Field } from 'formik'; 17 | 18 | const AutoSubmitToken = () => { 19 | // Grab values and submitForm from context 20 | const { values, submitForm } = useFormikContext(); 21 | React.useEffect(() => { 22 | // Submit the form imperatively as an effect as soon as form values.token are 6 digits long 23 | if (values.token.length === 6) { 24 | submitForm(); 25 | } 26 | }, [values, submitForm]); 27 | return null; 28 | }; 29 | 30 | const TwoFactorVerificationForm = () => ( 31 |
32 |

2-step Verification

33 |

Please enter the 6 digit code sent to your device

34 | { 37 | const errors = {}; 38 | if (values.token.length < 5) { 39 | errors.token = 'Invalid code. Too short.' 40 | } 41 | return errors 42 | }} 43 | onSubmit={(values, actions) => { 44 | setTimeout(() => { 45 | alert(JSON.stringify(values, null, 2)); 46 | actions.setSubmitting(false); 47 | }, 1000); 48 | }} 49 | > 50 |
51 | 52 | 53 | 54 |
55 |
56 | ); 57 | ``` 58 | 59 | --- 60 | 61 | # Reference 62 | 63 | ## `useFormikContext(): FormikProps` 64 | 65 | A custom React Hook that returns Formik states and helpers via React Context. Thus, this hook will only work if there is a parent Formik React Context from which it can pull from. If called without a parent context (i.e. a descendent of a `` component or `withFormik` higher-order component), you will get a warning in your console. 66 | -------------------------------------------------------------------------------- /examples/SchemaValidation.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Formik, Field, Form, ErrorMessage } from 'formik'; 3 | import * as Yup from 'yup'; 4 | import { Debug } from './Debug'; 5 | 6 | // While you can use any validation library (or write you own), Formik 7 | // comes with special support for Yup by @jquense. It has a builder API like 8 | // React PropTypes / Hapi.js's Joi. You can define these inline or, you may want 9 | // to keep them separate so you can reuse schemas (e.g. address) across your application. 10 | const SignUpSchema = Yup.object().shape({ 11 | email: Yup.string() 12 | .email('Invalid email address') 13 | .required('Required'), 14 | firstName: Yup.string() 15 | .min(2, 'Must be longer than 2 characters') 16 | .max(20, 'Nice try, nobody has a first name that long') 17 | .required('Required'), 18 | lastName: Yup.string() 19 | .min(2, 'Must be longer than 2 characters') 20 | .max(20, 'Nice try, nobody has a last name that long') 21 | .required('Required'), 22 | }); 23 | 24 | const SignUp = () => ( 25 |
26 |

Sign up

27 | { 35 | setTimeout(() => { 36 | alert(JSON.stringify(values, null, 2)); 37 | }, 500); 38 | }} 39 | render={({ errors, touched }) => ( 40 |
41 | 42 | 43 | 44 | 49 | 50 | 51 | 52 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | )} 66 | /> 67 |
68 | ); 69 | 70 | export default SignUp; 71 | -------------------------------------------------------------------------------- /examples/CombinedValidations.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Formik, Field, Form, ErrorMessage } from 'formik'; 3 | import * as Yup from 'yup'; 4 | import { Debug } from './Debug'; 5 | 6 | const Schema = Yup.object().shape({ 7 | email: Yup.string().required('This field is required'), 8 | }); 9 | 10 | // Async Validation 11 | const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); 12 | 13 | const validate = values => 14 | sleep(300).then(() => { 15 | return { 16 | zip: 'This field is required', 17 | }; 18 | }); 19 | 20 | const isRequired = message => value => (!!value ? undefined : message); 21 | 22 | const FieldLevelValidation = () => ( 23 |
24 |

Pick a username

25 | { 34 | sleep(500).then(() => { 35 | alert(JSON.stringify(values, null, 2)); 36 | }); 37 | }} 38 | render={({ 39 | errors, 40 | touched, 41 | setFieldValue, 42 | setFieldTouched, 43 | validateField, 44 | validateForm, 45 | }) => ( 46 |
47 | 48 |
49 | 55 | 56 |
57 |
58 |
59 | 65 | 66 |
67 |
68 |
69 | 75 | 76 |
77 |
78 | 79 | 80 | 81 | )} 82 | /> 83 |
84 | ); 85 | 86 | export default FieldLevelValidation; 87 | -------------------------------------------------------------------------------- /docs/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "routes": [ 3 | { 4 | "title": "Documentation", 5 | "heading": true, 6 | "routes": [ 7 | { 8 | "title": "Getting Started", 9 | "path": "/docs/overview.md" 10 | }, 11 | { 12 | "title": "Tutorial", 13 | "path": "/docs/tutorial.md" 14 | }, 15 | { 16 | "title": "Migrating from v1.x to v2.x", 17 | "path": "/docs/migrating-v2.md" 18 | }, 19 | { 20 | "title": "Resources", 21 | "path": "/docs/resources.md" 22 | }, 23 | { 24 | "title": "Guides", 25 | "open": true, 26 | "routes": [ 27 | { 28 | "title": "Validation", 29 | "path": "/docs/guides/validation.md" 30 | }, 31 | { 32 | "title": "Arrays", 33 | "path": "/docs/guides/arrays.md" 34 | }, 35 | { 36 | "title": "TypeScript", 37 | "path": "/docs/guides/typescript.md" 38 | }, 39 | { 40 | "title": "React Native", 41 | "path": "/docs/guides/react-native.md" 42 | }, 43 | { 44 | "title": "Form Submission", 45 | "path": "/docs/guides/form-submission.md" 46 | } 47 | ] 48 | } 49 | ] 50 | }, 51 | { 52 | "title": "API Reference", 53 | "heading": true, 54 | "routes": [ 55 | { "title": "connect()", "path": "/docs/api/connect.md" }, 56 | { 57 | "title": "", 58 | "path": "/docs/api/errormessage.md" 59 | }, 60 | { "title": "", "path": "/docs/api/fastfield.md" }, 61 | { "title": "", "path": "/docs/api/field.md" }, 62 | { "title": "", "path": "/docs/api/fieldarray.md" }, 63 | { "title": "
", "path": "/docs/api/form.md" }, 64 | { "title": "", "path": "/docs/api/formik.md" }, 65 | { "title": "useField()", "path": "/docs/api/useField.md" }, 66 | { 67 | "title": "useFormik()", 68 | "path": "/docs/api/useFormik.md" 69 | }, 70 | { 71 | "title": "useFormikContext()", 72 | "path": "/docs/api/useFormikContext.md" 73 | }, 74 | { "title": "withFormik()", "path": "/docs/api/withFormik.md" } 75 | ] 76 | } 77 | ] 78 | } 79 | -------------------------------------------------------------------------------- /examples/ErrorMessage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Formik, Field, Form, ErrorMessage } from 'formik'; 3 | import * as Yup from 'yup'; 4 | import { Debug } from './Debug'; 5 | 6 | // While you can use any validation library (or write you own), Formik 7 | // comes with special support for Yup by @jquense. It has a builder API like 8 | // React PropTypes / Hapi.js's Joi. You can define these inline or, you may want 9 | // to keep them separate so you can reuse schemas (e.g. address) across your application. 10 | const SignUpSchema = Yup.object().shape({ 11 | email: Yup.string() 12 | .email('Invalid email address') 13 | .required('Required'), 14 | firstName: Yup.string() 15 | .min(2, 'Must be longer than 2 characters') 16 | .max(20, 'Nice try, nobody has a first name that long') 17 | .required('Required'), 18 | lastName: Yup.string() 19 | .min(2, 'Must be longer than 2 characters') 20 | .max(20, 'Nice try, nobody has a last name that long') 21 | .required('Required'), 22 | }); 23 | 24 | // will ONLY render when a field has an error and has been touched. 25 | const SignUp = () => ( 26 |
27 |

Sign up

28 | { 36 | setTimeout(() => { 37 | alert(JSON.stringify(values, null, 2)); 38 | }, 500); 39 | }} 40 | render={({ errors, touched }) => ( 41 | 42 | 43 | 44 | 49 | 50 | 51 | 52 | 53 | {(msg /** this is the same as the above */) => ( 54 |
{msg}
55 | )} 56 |
57 | 58 | 59 | 60 | {/* This will render a string */} 61 | 62 | 63 | 64 | 65 | 66 | )} 67 | /> 68 |
69 | ); 70 | 71 | export default SignUp; 72 | -------------------------------------------------------------------------------- /examples/FieldLevelValidation.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Formik, Field, Form, ErrorMessage } from 'formik'; 3 | import { Debug } from './Debug'; 4 | 5 | const isRequired = message => value => (!!value ? undefined : message); 6 | 7 | const FieldLevelValidation = () => ( 8 |
9 |

Pick a username

10 | { 13 | alert(JSON.stringify(values, null, 2)); 14 | }} 15 | render={({ 16 | errors, 17 | touched, 18 | setFieldValue, 19 | setFieldTouched, 20 | validateField, 21 | validateForm, 22 | }) => ( 23 |
24 | 25 |
26 | 32 | 33 |
34 |
35 |
36 | 42 | 43 |
44 | 45 |
46 |
username field actions
47 | 55 | 63 | 71 |
72 |
73 |
74 |
75 |
Form actions
76 | 79 | 80 |
81 | 82 | 83 | )} 84 | /> 85 |
86 | ); 87 | 88 | export default FieldLevelValidation; 89 | -------------------------------------------------------------------------------- /docs/api/useFormik.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: useFormik 3 | title: useFormik() 4 | custom_edit_url: https://github.com/jaredpalmer/formik/edit/master/docs/api/useFormik.md 5 | --- 6 | 7 | `useFormik()` is a custom React hook that will return all Formik state and helpers directly. Despite its name, it is not meant for the majority of use cases. Internally, Formik uses `useFormik` to create the `` component (which renders a [React Context](https://reactjs.org/docs/context.html) Provider). If you are trying to access Formik state via context, use [useFormikContext](useFormikContext). Only use this hook if you are NOT using `` or `withFormik`. 8 | 9 | \*\* Be aware that ``, ``, ``, `connect()`, and `` will NOT work with `useFormik()` as they all require React Context. 10 | 11 | ## Use cases for `useFormik()` 12 | 13 | - You are Jared 14 | - You are modifying the returned value and creating a modified version of `` for your own consumption 15 | - You want to avoid using React Context (possibly for perf reasons) 16 | 17 | ## Example 18 | 19 | ```jsx 20 | import React from 'react'; 21 | import { useFormik } from 'formik'; 22 | 23 | const SignupForm = () => { 24 | const formik = useFormik({ 25 | initialValues: { 26 | firstName: '', 27 | lastName: '', 28 | email: '', 29 | }, 30 | onSubmit: values => { 31 | alert(JSON.stringify(values, null, 2)); 32 | }, 33 | }); 34 | return ( 35 |
36 | 37 | 44 | 45 | 52 | 53 | 60 | 61 |
62 | ); 63 | }; 64 | ``` 65 | 66 | --- 67 | 68 | # Reference 69 | 70 | ## `useFormik(config: FormikConfig): FormikProps` 71 | 72 | A custom React Hook that returns Formik states and helpers. It is used internally to create the `` component, but is exported for advanced use cases or for those people that do not want to use React Context. 73 | -------------------------------------------------------------------------------- /examples/ValidateFieldWithSchema.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Formik, Field, Form, ErrorMessage } from 'formik'; 3 | import { object, string } from 'yup'; 4 | import { Debug } from './Debug'; 5 | 6 | const validationSchema = object().shape({ 7 | email: string() 8 | .email('Invalid email') 9 | .required('Field is required'), 10 | username: string() 11 | .min(4, 'Must be at least 4 characters') 12 | .required('Field is required'), 13 | }); 14 | 15 | const ValidateFieldWithSchema = () => ( 16 |
17 |

Pick a username

18 | { 22 | alert(JSON.stringify(values, null, 2)); 23 | }} 24 | render={({ 25 | errors, 26 | touched, 27 | setFieldValue, 28 | setFieldTouched, 29 | validateField, 30 | validateForm, 31 | }) => ( 32 |
33 | 34 |
35 | 40 | 41 |
42 |
43 |
44 | 49 | 50 |
51 | 52 |
53 |
username field actions
54 | 62 | 70 | 78 |
79 |
80 |
81 |
82 |
Form actions
83 | 86 | 87 |
88 | 89 | 90 | )} 91 | /> 92 |
93 | ); 94 | 95 | export default ValidateFieldWithSchema; 96 | -------------------------------------------------------------------------------- /packages/formik/test/yupHelpers.test.ts: -------------------------------------------------------------------------------- 1 | import { validateYupSchema, yupToFormErrors } from '../src'; 2 | 3 | const Yup = require('yup'); 4 | const schema = Yup.object().shape({ 5 | name: Yup.string('Name must be a string').required('required'), 6 | field: Yup.string('Field must be a string'), 7 | }); 8 | const nestedSchema = Yup.object().shape({ 9 | object: Yup.object().shape({ 10 | nestedField: Yup.string('Field must be a string'), 11 | nestedArray: Yup.array().of( 12 | Yup.string('Field must be a string').nullable() 13 | ), 14 | }), 15 | }); 16 | 17 | describe('Yup helpers', () => { 18 | describe('yupToFormErrors()', () => { 19 | it('should transform Yup ValidationErrors into an object', async () => { 20 | try { 21 | await schema.validate({}, { abortEarly: false }); 22 | } catch (e) { 23 | expect(yupToFormErrors(e)).toEqual({ 24 | name: 'required', 25 | }); 26 | } 27 | }); 28 | }); 29 | 30 | describe('validateYupSchema()', () => { 31 | it('should validate', async () => { 32 | try { 33 | await validateYupSchema({}, schema); 34 | } catch (e) { 35 | expect(e.name).toEqual('ValidationError'); 36 | expect(e.errors).toEqual(['required']); 37 | } 38 | }); 39 | 40 | it('should stringify all values', async () => { 41 | try { 42 | const result = await validateYupSchema({ name: 1 }, schema); 43 | expect(result).not.toEqual({ name: 1 }); 44 | expect(result).toEqual({ name: '1' }); 45 | } catch (e) { 46 | throw e; 47 | } 48 | }); 49 | 50 | it('should set undefined empty strings', async () => { 51 | try { 52 | const result = await validateYupSchema( 53 | { name: 'foo', field: '' }, 54 | schema 55 | ); 56 | expect(result.field).toBeUndefined(); 57 | } catch (e) { 58 | throw e; 59 | } 60 | }); 61 | 62 | it('should set undefined nested empty strings', async () => { 63 | try { 64 | const result = await validateYupSchema( 65 | { name: 'foo', object: { nestedField: '' } }, 66 | nestedSchema 67 | ); 68 | expect(result.object!.nestedField).toBeUndefined(); 69 | } catch (e) { 70 | throw e; 71 | } 72 | }); 73 | 74 | it('should set undefined nested empty strings', async () => { 75 | try { 76 | const result = await validateYupSchema( 77 | { 78 | name: 'foo', 79 | object: { nestedField: 'swag', nestedArray: ['', 'foo', 'bar'] }, 80 | }, 81 | nestedSchema 82 | ); 83 | expect(result.object!.nestedArray!).toEqual([undefined, 'foo', 'bar']); 84 | } catch (e) { 85 | throw e; 86 | } 87 | }); 88 | }); 89 | }); 90 | -------------------------------------------------------------------------------- /examples/CustomInputs.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Formik, Field, Form, ErrorMessage } from 'formik'; 3 | import * as Yup from 'yup'; 4 | import { Debug } from './Debug'; 5 | 6 | // By combining a vanilla