Skip to content

Commit

Permalink
types: Align FormikHelpers and FieldHelper types to useFormik ones (#…
Browse files Browse the repository at this point in the history
…3843)

This is yet another PR around TypeScript.

The inferred types for the helpers in `useFormik` are the correct ones and should be used everywhere.
See
```
export declare function useFormik<Values extends FormikValues = FormikValues>({ validateOnChange, validateOnBlur, validateOnMount, isInitialValid, enableReinitialize, onSubmit, ...rest }: FormikConfig<Values>): {
   
   [...redacted for readability...]
   
    setFieldTouched: (field: string, touched?: boolean, shouldValidate?: boolean) => Promise<FormikErrors<Values>> | Promise<void>;
    setFieldValue: (field: string, value: any, shouldValidate?: boolean) => Promise<FormikErrors<Values>> | Promise<void>;
    setFieldError: (field: string, value: string | undefined) => void;
    setStatus: (status: any) => void;
    setSubmitting: (isSubmitting: boolean) => void;
    setTouched: (touched: FormikTouched<Values>, shouldValidate?: boolean) => Promise<FormikErrors<Values>> | Promise<void>;
    setValues: (values: React.SetStateAction<Values>, shouldValidate?: boolean) => Promise<FormikErrors<Values>> | Promise<void>;
    submitForm: () => Promise<any>;
    validateForm: (values?: Values) => Promise<FormikErrors<Values>>;
    validateField: (name: string) => Promise<void> | Promise<string | undefined>;
    
    [...redacted for readability...]
};
```

Having the correct types, and the awaiting these helpers helps with otherwise possible race conditions when used in an imperative way, like so
```
const handleChange = ({ target }) => {
  await setFieldTouched('fieldName', true, false) 
  await setFieldValue('fieldName', target.value, false)
  await validateField('fieldName')
}
```
  • Loading branch information
bonimba committed Aug 2, 2023
1 parent b35b9ba commit 9e0a661
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/nervous-flowers-rule.md
@@ -0,0 +1,5 @@
---
'formik': patch
---

Fix FormikHelper and FieldHelperProps types
10 changes: 8 additions & 2 deletions docs/api/formik.md
Expand Up @@ -177,11 +177,13 @@ Set `errors` imperatively.
Set the error message of a field imperatively. `field` should match the key of
`errors` you wish to update. Useful for creating custom input error handlers.

#### `setFieldTouched: (field: string, isTouched?: boolean, shouldValidate?: boolean) => void`
#### `setFieldTouched: (field: string, isTouched?: boolean, shouldValidate?: boolean) => Promise<void | FormikErrors>`

Set the touched state of a field imperatively. `field` should match the key of
`touched` you wish to update. Useful for creating custom input blur handlers. Calling this method will trigger validation to run if `validateOnBlur` is set to `true` (which it is by default). `isTouched` defaults to `true` if not specified. You can also explicitly prevent/skip validation by passing a third argument as `false`.

If `validateOnBlur` is set to `true` and there are errors, they will be resolved in the returned `Promise`.

#### `submitForm: () => Promise`

Trigger a form submission. The promise will be rejected if form is invalid.
Expand All @@ -208,14 +210,18 @@ use it to pass API responses back into your component in `handleSubmit`.

Set `isSubmitting` imperatively. You would call it with `setSubmitting(false)` in your `onSubmit` handler to finish the cycle. To learn more about the submission process, see [Form Submission](../guides/form-submission.md).

#### `setTouched: (fields: { [field: string]: boolean }, shouldValidate?: boolean) => void`
#### `setTouched: (fields: { [field: string]: boolean }, shouldValidate?: boolean) => Promise<void | FormikErrors>`

Set `touched` imperatively. Calling this will trigger validation to run if `validateOnBlur` is set to `true` (which it is by default). You can also explicitly prevent/skip validation by passing a second argument as `false`.

If `validateOnBlur` is set to `true` and there are errors, they will be resolved in the returned `Promise`.

#### `setValues: (fields: React.SetStateAction<{ [field: string]: any }>, shouldValidate?: boolean) => void`

Set `values` imperatively. Calling this will trigger validation to run if `validateOnChange` is set to `true` (which it is by default). You can also explicitly prevent/skip validation by passing a second argument as `false`.

If `validateOnChange` is set to `true` and there are errors, they will be resolved in the returned `Promise`.

#### `status?: any`

A top-level status object that you can use to represent form state that can't
Expand Down
6 changes: 5 additions & 1 deletion docs/api/useField.md
Expand Up @@ -159,6 +159,10 @@ An object that contains relevant computed metadata about a field. More specifica

An object that contains helper functions which you can use to imperatively change the value, error value or touched status for the field in question. This is useful for components which need to change a field's status directly, without triggering change or blur events.

- `setValue(value: any, shouldValidate?: boolean): void` - A function to change the field's value. Calling this will trigger validation to run if `validateOnChange` is set to `true` (which it is by default). You can also explicitly prevent/skip validation by passing a second argument as `false`.
- `setValue(value: any, shouldValidate?: boolean): Promise<void | FormikErrors>` - A function to change the field's value. Calling this will trigger validation to run if `validateOnChange` is set to `true` (which it is by default). You can also explicitly prevent/skip validation by passing a second argument as `false`.
If `validateOnChange` is set to `true` and there are errors, they will be resolved in the returned `Promise`.

- `setTouched(value: boolean, shouldValidate?: boolean): void` - A function to change the field's touched status. Calling this will trigger validation to run if `validateOnBlur` is set to `true` (which it is by default). You can also explicitly prevent/skip validation by passing a second argument as `false`.
If `validateOnBlur` is set to `true` and there are errors, they will be resolved in the returned `Promise`.

- `setError(value: any): void` - A function to change the field's error value
12 changes: 6 additions & 6 deletions packages/formik/src/types.tsx
Expand Up @@ -86,12 +86,12 @@ export interface FormikHelpers<Values> {
setTouched: (
touched: FormikTouched<Values>,
shouldValidate?: boolean
) => void;
) => Promise<void | FormikErrors<Values>>;
/** Manually set values object */
setValues: (
values: React.SetStateAction<Values>,
shouldValidate?: boolean
) => void;
) => Promise<void | FormikErrors<Values>>;
/** Set value of form field directly */
setFieldValue: (
field: string,
Expand All @@ -105,11 +105,11 @@ export interface FormikHelpers<Values> {
field: string,
isTouched?: boolean,
shouldValidate?: boolean
) => void;
) => Promise<void | FormikErrors<Values>>;
/** Validate form values */
validateForm: (values?: any) => Promise<FormikErrors<Values>>;
/** Validate field value */
validateField: (field: string) => void;
validateField: (field: string) => Promise<void> | Promise<string | undefined>;
/** Reset form */
resetForm: (nextState?: Partial<FormikState<Values>>) => void;
/** Submit the form imperatively */
Expand Down Expand Up @@ -302,9 +302,9 @@ export interface FieldMetaProps<Value> {
/** Imperative handles to change a field's value, error and touched */
export interface FieldHelperProps<Value> {
/** Set the field's value */
setValue: (value: Value, shouldValidate?: boolean) => void;
setValue: (value: Value, shouldValidate?: boolean) => Promise<void | FormikErrors<Value>>;
/** Set the field's touched value */
setTouched: (value: boolean, shouldValidate?: boolean) => void;
setTouched: (value: boolean, shouldValidate?: boolean) => Promise<void | FormikErrors<Value>>;
/** Set the field's error value */
setError: (value: string | undefined) => void;
}
Expand Down

1 comment on commit 9e0a661

@vercel
Copy link

@vercel vercel bot commented on 9e0a661 Aug 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

formik-docs – ./website

formik.org
formik-docs-git-main-formik.vercel.app
formik-docs.vercel.app
formik-docs-formik.vercel.app
www.formik.org

Please sign in to comment.