diff --git a/website/.gitignore b/website/.gitignore index ae0da2473..f2d804c96 100644 --- a/website/.gitignore +++ b/website/.gitignore @@ -6,4 +6,5 @@ node_modules *.log .DS_Store .vercel -public/sitemap.xml \ No newline at end of file +public/sitemap.xml +.source \ No newline at end of file diff --git a/website/content/blog/formik-3-alpha.mdx b/website/content/blog/formik-3-alpha.mdx new file mode 100644 index 000000000..b4a613b98 --- /dev/null +++ b/website/content/blog/formik-3-alpha.mdx @@ -0,0 +1,138 @@ +--- +title: Formik 3 Alpha +date: 2020-10-27 +published: true +slug: formik-3-alpha +authors: + - Jared Palmer +preview: | + Today, we cut the very first release of Formik v3 alpha. The reason for this blog post is that there is a small breaking change that we unfortunately have no way of warning you about like we usually do with deprecation notices due to its nature. +--- + +Today, we cut the very first release of Formik v3 alpha. You can install it with: + +```jsx +npm install formik@next +``` + +The reason for this blog post is that there is a small breaking change that we unfortunately have no way of warning you about like we usually do with deprecation notices due to its nature. + +--- + +But, before we get into the bad news, let's first share the good news: + +## New `parse`, `format`, and `formatOnBlur` props! + +The new alpha release contains new `parse` , `format`, and `formatOnBlur` props for `getFieldProps`, ``, and `useField()`. These props make it a lot easier to implement [input masking](https://css-tricks.com/input-masking/)—a technique where you alter the format of the raw value of an input to make it appear in a certain way to the user (e.g. like a phone number (917) 555-1234 or a text-based date 10/2020). For you TypeScript friends here's what's new: + +```tsx +interface FieldConfig { + // ...omitted for brevity + + /** + * Function to parse raw input value before setting it to state + */ + parse?: (rawInput: string, name: string) => V; + + /** + * Function to transform value passed to input + */ + format?: (value: V, name: string) => any; + + /** + * Should Formik wait until the blur event before formatting input value? + * @default false + */ + formatOnBlur?: boolean; +} + +// ...elsewhere... + +const [field] = useField({ name: 'phone', parse: rawInput => ... }) + ... } /> + ... }) /> +``` + +And here's a full example that uses the `[format-string-by-pattern](https://www.npmjs.com/package/format-string-by-pattern)` package to create various phone number input masks. Notice on the first input that even though you type 9999999999 the input's value (and Formik's internal value) is 999-999-9999. Neat! + +[https://codesandbox.io/s/github/jaredpalmer/formik/tree/next/examples/format-string-by-pattern?fontsize=14&hidenavigation=1&theme=dark&file=/index.js](https://codesandbox.io/s/github/jaredpalmer/formik/tree/next/examples/format-string-by-pattern?fontsize=14&hidenavigation=1&theme=dark&file=/index.js) + +**\*Pro Tip:** I'm all about making intuitive API's and so I'm aware that `parse` and `format` are hard to remember. The trick I've been using / saying in my head is as follows: "format" → sounds like "from" → "from Formik" → from Formik to input. Again, this is an alpha, so if it's too confusing, we'll rename these.\* + +## A Breaking Change + +To support this new behavior, we needed to make a breaking change to the way that `onChange` and `onBlur` handlers work when returned from `formikProps.getFieldProps()`, which subsequently impacts `useField()` and `Field` as well. + +In the past, these `onChange` and `onBlur` methods were identical to `formikProps.handleChange` and `formikProps.handleBlur` (returned by `useFormik()` or by the render prop `` or `withFormik`). However, as of 3.0.0-next.0, these methods behave differently, respectively. + +When returned from `getFieldProps`, `useField`, or ``'s render prop, `onChange` and `onBlur` are now already scoped to the given field and can now accept either a React Synthetic event or an arbitrary value. They no longer can be curried like `handleChange` and `handleBlur` can. + +### Some Examples + +Here are some more concrete examples for you of what works and what doesn't work... + +**Still works, but does not support `parse`, `format`, and `formatOnBlur`** + +```tsx +export const MyReactNativeForm = props => ( + console.log(values)} + > + {({ handleChange, handleBlur, handleSubmit, values }) => ( + + + + + )} + + +); +``` + +#### Props + +--- + +# Reference + +## Props + +### `children` + +`children?: ((message: string) => React.ReactNode)` + +A function that returns a valid React element. Will only be called when the field has been touched and an error exists. + +```jsx +// the render callback will only be called when the +// field has been touched and an error exists and subsequent updates. +{msg =>
{msg}
}
+``` + +### `component` + +`component?: string | React.ComponentType` + +Either a React component or the name of an HTML element to render. If not specified, `` will just return a string. + +```jsx + +// --> {touched.email && error.email ?
{error.email}
: null} + + +// --> {touched.email && error.email ? {error.email} : null} + + +// --> {touched.email && error.email ? {error.email} : null} + + +// This will return a string. React 16+. +// --> {touched.email && error.email ? error.email : null} +``` + +### `id` + +`id?: string` + +A field's id in Formik state. To get access to DOM elements for e2e testing purposes, it doesn't impact the implementation in any way as the prop can still be omitted. +```jsx +// id will be used only for testing purposes +// not contributing anything to the core implementation. + +``` + +### `name` + +`name: string` +**Required** + +A field's name in Formik state. To access nested objects or arrays, name can also accept lodash-like dot path like `social.facebook` or `friends[0].firstName` + +### `render` + +`render?: (error: string) => React.ReactNode` + +A function that returns a valid React element. Will only be called when the field has been touched and an error exists. + +```jsx +// the render callback will only be called when the +// field has been touched and an error exists and subsequent updates. +
{msg}
} /> +``` diff --git a/website/content/docs/api/fastfield.mdx b/website/content/docs/api/fastfield.mdx new file mode 100644 index 000000000..32fa48ee3 --- /dev/null +++ b/website/content/docs/api/fastfield.mdx @@ -0,0 +1,132 @@ +--- +id: fastfield +title: +--- + +## Before we start + +`` is meant for performance _optimization_. However, you really do not need to use it until you do. Only proceed if you are familiar with how React's [`shouldComponentUpdate()`](https://reactjs.org/docs/react-component.html#shouldcomponentupdate) works. You have been warned. + +**No. Seriously. Please review the following parts of the official React documentation before continuing** + +- [React `shouldComponentUpdate()` Reference](https://reactjs.org/docs/react-component.html#shouldcomponentupdate) +- [`shouldComponentUpdate` in Action](https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action) + +## Overview + +`` is an optimized version of `` meant to be used on large forms (~30+ fields) or when a field has very expensive validation requirements. `` has the same exact API as ``, but implements `shouldComponentUpdate()` internally to block all additional re-renders unless there are direct updates to the ``'s relevant parts/slice of Formik state. + +For example, `` will only re-render when there are: + +- Changes to `values.firstName`, `errors.firstName`, `touched.firstName`, or `isSubmitting`. This is determined by shallow comparison. Note: dotpaths are supported. +- A prop is added/removed to the `` +- The `name` prop changes + +Other than for these aforementioned situations, `` will not re-render when other parts of Formik state change. However, all updates triggered by a `` will trigger re-renders to other "vanilla" `` components. + +## When to use `` + +**If a `` is "independent" of all other ``'s in your form, then you can use ``**. + +More specifically, if the `` does not change behavior or render anything that is based on updates to another `` or ``'s slice of Formik state AND it does not rely on other parts of top-level `` state (e.g. `isValidating`, `submitCount`), then you can use `` as a drop-in replacement to ``. + +## Example + +```jsx +import React from 'react'; +import { Formik, Field, FastField, Form } from 'formik'; +import * as Yup from 'yup'; + +const Basic = () => ( +
+

Sign Up

+ { + setTimeout(() => { + alert(JSON.stringify(values, null, 2)); + }, 500); + }} + > + {formikProps => ( +
+ {/** This only updates for changes made to + values.firstName, touched.firstName, errors.firstName */} + + + + {/** Updates for all changes because it's from the + top-level formikProps which get all updates */} + {formikProps.touched.firstName && formikProps.errors.firstName && ( +
{formikProps.errors.firstName}
+ )} + + + + {({ field, form, meta }) => ( +
+ + {/** + * This updates normally because it's from the same slice of Formik state, + * i.e. path to the object matches the name of this + */} + {meta.touched ? meta.error : null} + + {/** This won't ever update since it's coming from + from another /'s (i.e. firstName's) slice */} + {form.touched.firstName && form.errors.firstName + ? form.errors.firstName + : null} + + {/* This doesn't update either */} + {form.submitCount} + + {/* Imperative methods still work as expected */} + +
+ )} +
+ + {/** Updates for all changes to Formik state + and all changes by all s and s */} + + + {({ field, form, meta }) => ( +
+ + {/** Works because this is inside + of a , which gets all updates */} + {form.touched.firstName && form.errors.firstName + ? form.errors.firstName + : null} +
+ )} +
+ + {/** Updates for all changes to Formik state and + all changes by all s and s */} + + + + + + )} +
+
+); +``` diff --git a/website/content/docs/api/field.mdx b/website/content/docs/api/field.mdx new file mode 100644 index 000000000..a2c1002c6 --- /dev/null +++ b/website/content/docs/api/field.mdx @@ -0,0 +1,310 @@ +--- +id: field +title: +--- + +`` will automagically hook up inputs to Formik. It uses the `name` +attribute to match up with Formik state. `` will default to an HTML +`` element. + +## Rendering + +There are a few different ways to render things with ``. + +- `` +- `` +- `` +- ~~``~~ _deprecated in 2.x. Using these will log warning_ + +`as` can either be a React component or the name of an HTML element to render. Formik will automagically inject `onChange`, `onBlur`, `name`, and `value` props of the field designated by the `name` prop to the (custom) component. + +`children` can either be an array of elements (e.g. `