diff --git a/docs/api/useFastField.md b/docs/api/useFastField.md new file mode 100644 index 000000000..b49eb9c6e --- /dev/null +++ b/docs/api/useFastField.md @@ -0,0 +1,112 @@ +--- +id: useFastField +title: useFastField() +custom_edit_url: https://github.com/jaredpalmer/formik/edit/master/docs/api/useFastField.md +--- + +`useFastField` is a custom React hook that will automagically help you hook up inputs in a similar way to `useField`. +The `useFastField` behaviour imitates `useField` when Formik is configured to validate onBlur. The Formik model is not updated after an onChange event, only the input field is updated. After an onBlur event occurs, the Formik v model is updated resulting in a more performant way at the expense of some minor differences. There are 2 ways to use it. + +## Example + +```tsx +import React from 'react'; +import { useFastField, Formik } from 'formik'; + +const MyTextField = ({ label, ...props }) => { + const [field, meta] = useFastField(props.name); + return ( + <> + + {meta.touched && meta.error ? ( +
{meta.error}
+ ) : null} + + ); +}; + +const Example = () => ( +
+

My Form

+ { + setTimeout(() => { + alert(JSON.stringify(values, null, 2)); + actions.setSubmitting(false); + }, 1000); + }} + render={(props: FormikProps) => ( +
+ + + + + + )} + /> +
+); +``` + +--- + +# Reference + +## `useFastField(name: string): [FieldInputProps, FieldMetaProps]` + +A custom React Hook that returns a tuple (2 element array) containing `FieldProps` and `FieldMetaProps`. It accepts either a string of a field name or an object as an argument. The object must at least contain a `name` key. This object should identical to the props that you would pass to `` and the returned helpers will imitate the behavior of ``. This is useful, and generally preferred, since it allows you to take advantage of formik's checkbox, radio, and multiple select behavior when the object contains the relevant key/values (e.g. `type: 'checkbox'`, `multiple: true`, etc.). + +```jsx +import React from 'react'; +import { useFastField } from 'formik'; + +function MyTextField(props) { + // this will return field props for an + const [field, meta] = useFastField(props.name); + return ( + <> + + {meta.error && meta.touched &&
{meta.error}
} + + ); +} + +function MyInput(props) { + // this will return field exactly like {({ field }) => ... } + const [field, meta] = useFastField(props); + return ( + <> + + {meta.error && meta.touched &&
{meta.error}
} + + ); +} +``` + +### `FieldInputProps` + +An object that contains: + +- `name: string` - The name of the field +- `checked?: boolean` - Whether or not the input is checked, this is only defined if `useField` is passed an object with a `name`, `type: "checkbox"` or `type: radio`. +- `onBlur: () => void;` - A blur event handler +- `onChange: (e: React.ChangeEvent) => void` - A change event handler +- `value: any` - The field's value (plucked out of `values`) or, if it is a checkbox or radio input, then potentially the `value` passed into `useField`. +- `multiple?: boolean` - Whether or not the multiple values can be selected. This is only ever defined when `useField` is passed an object with `multiple: true` + +for a given field in Formik state. This is to avoid needing to manually wire up inputs. + +### `FieldMetaProps` + +An object that contains relevant computed metadata about a field. More specifically, + +- `error?: string` - The field's error message (plucked out of `errors`) +- `initialError?: string` - The field's initial error if the field is present in `initialErrors` (plucked out of `initialErrors`) +- `initialTouched: boolean` - The field's initial value if the field is present in `initialTouched` (plucked out of `initialTouched`) +- `initialValue?: any` - The field's initial value if the field is given a value in `initialValues` (plucked out of `initialValues`) +- `touched: boolean` - Whether the field has been visited (plucked out of `touched`) +- `value: any` - The field's value (plucked out of `values`) diff --git a/src/Field.tsx b/src/Field.tsx index e2fe1e830..3354d7cfc 100644 --- a/src/Field.tsx +++ b/src/Field.tsx @@ -92,6 +92,27 @@ export function useField( return formik.getFieldProps({ name: propsOrFieldName }); } +export function useFastField( + props: FieldAttributes +): [FieldInputProps, FieldMetaProps] { + const [field, meta] = useField(props); + const [value, setValue] = React.useState(field.value); + const { onBlur, onChange } = field; + + field.value = value; + field.onChange = (e: any): void => { + if (e && e.currentTarget) { + setValue(e.currentTarget.value); + } + }; + field.onBlur = (e: any): void => { + onChange(e); + onBlur(e); + }; + + return [field, meta]; +} + export function Field({ validate, name, diff --git a/website/sidebars.json b/website/sidebars.json index 1b0f8a7b1..a3ca76b34 100644 --- a/website/sidebars.json +++ b/website/sidebars.json @@ -1,7 +1,24 @@ { "docs": { "Getting Started": ["overview", "tutorial", "resources"], - "Guides": ["guides/validation", "guides/arrays", "guides/typescript", "guides/react-native", "guides/form-submission"], - "API Reference": ["api/formik", "api/withFormik", "api/field", "api/usefield", "api/fieldarray", "api/form", "api/errormessage", "api/connect", "api/fastfield"] + "Guides": [ + "guides/validation", + "guides/arrays", + "guides/typescript", + "guides/react-native", + "guides/form-submission" + ], + "API Reference": [ + "api/formik", + "api/withFormik", + "api/field", + "api/usefield", + "api/usefastfield", + "api/fieldarray", + "api/form", + "api/errormessage", + "api/connect", + "api/fastfield" + ] } -} \ No newline at end of file +}