Skip to content

Commit 9e0a661

Browse files
authored
types: Align FormikHelpers and FieldHelper types to useFormik ones (#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') } ```
1 parent b35b9ba commit 9e0a661

File tree

4 files changed

+24
-9
lines changed

4 files changed

+24
-9
lines changed

.changeset/nervous-flowers-rule.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'formik': patch
3+
---
4+
5+
Fix FormikHelper and FieldHelperProps types

docs/api/formik.md

+8-2
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,13 @@ Set `errors` imperatively.
177177
Set the error message of a field imperatively. `field` should match the key of
178178
`errors` you wish to update. Useful for creating custom input error handlers.
179179

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

182182
Set the touched state of a field imperatively. `field` should match the key of
183183
`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`.
184184

185+
If `validateOnBlur` is set to `true` and there are errors, they will be resolved in the returned `Promise`.
186+
185187
#### `submitForm: () => Promise`
186188

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

209211
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).
210212

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

213215
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`.
214216

217+
If `validateOnBlur` is set to `true` and there are errors, they will be resolved in the returned `Promise`.
218+
215219
#### `setValues: (fields: React.SetStateAction<{ [field: string]: any }>, shouldValidate?: boolean) => void`
216220

217221
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`.
218222

223+
If `validateOnChange` is set to `true` and there are errors, they will be resolved in the returned `Promise`.
224+
219225
#### `status?: any`
220226

221227
A top-level status object that you can use to represent form state that can't

docs/api/useField.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ An object that contains relevant computed metadata about a field. More specifica
159159

160160
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.
161161

162-
- `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`.
162+
- `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`.
163+
If `validateOnChange` is set to `true` and there are errors, they will be resolved in the returned `Promise`.
164+
163165
- `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`.
166+
If `validateOnBlur` is set to `true` and there are errors, they will be resolved in the returned `Promise`.
167+
164168
- `setError(value: any): void` - A function to change the field's error value

packages/formik/src/types.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,12 @@ export interface FormikHelpers<Values> {
8686
setTouched: (
8787
touched: FormikTouched<Values>,
8888
shouldValidate?: boolean
89-
) => void;
89+
) => Promise<void | FormikErrors<Values>>;
9090
/** Manually set values object */
9191
setValues: (
9292
values: React.SetStateAction<Values>,
9393
shouldValidate?: boolean
94-
) => void;
94+
) => Promise<void | FormikErrors<Values>>;
9595
/** Set value of form field directly */
9696
setFieldValue: (
9797
field: string,
@@ -105,11 +105,11 @@ export interface FormikHelpers<Values> {
105105
field: string,
106106
isTouched?: boolean,
107107
shouldValidate?: boolean
108-
) => void;
108+
) => Promise<void | FormikErrors<Values>>;
109109
/** Validate form values */
110110
validateForm: (values?: any) => Promise<FormikErrors<Values>>;
111111
/** Validate field value */
112-
validateField: (field: string) => void;
112+
validateField: (field: string) => Promise<void> | Promise<string | undefined>;
113113
/** Reset form */
114114
resetForm: (nextState?: Partial<FormikState<Values>>) => void;
115115
/** Submit the form imperatively */
@@ -302,9 +302,9 @@ export interface FieldMetaProps<Value> {
302302
/** Imperative handles to change a field's value, error and touched */
303303
export interface FieldHelperProps<Value> {
304304
/** Set the field's value */
305-
setValue: (value: Value, shouldValidate?: boolean) => void;
305+
setValue: (value: Value, shouldValidate?: boolean) => Promise<void | FormikErrors<Value>>;
306306
/** Set the field's touched value */
307-
setTouched: (value: boolean, shouldValidate?: boolean) => void;
307+
setTouched: (value: boolean, shouldValidate?: boolean) => Promise<void | FormikErrors<Value>>;
308308
/** Set the field's error value */
309309
setError: (value: string | undefined) => void;
310310
}

0 commit comments

Comments
 (0)