formik
Version:
Build forms in React, without the tears
250 lines (249 loc) • 10.4 kB
TypeScript
import * as React from 'react';
import { FieldConfig } from './Field';
/**
* Values of fields in the form
*/
export interface FormikValues {
[field: string]: any;
}
/**
* An object containing error messages whose keys correspond to FormikValues.
* Should always be an object of strings, but any is allowed to support i18n libraries.
*/
export type FormikErrors<Values> = {
[K in keyof Values]?: Values[K] extends any[] ? Values[K][number] extends object ? FormikErrors<Values[K][number]>[] | string | string[] : string | string[] : Values[K] extends object ? FormikErrors<Values[K]> : string;
};
/**
* An object containing touched state of the form whose keys correspond to FormikValues.
*/
export type FormikTouched<Values> = {
[K in keyof Values]?: Values[K] extends any[] ? Values[K][number] extends object ? FormikTouched<Values[K][number]>[] : boolean : Values[K] extends object ? FormikTouched<Values[K]> : boolean;
};
/**
* Formik state tree
*/
export interface FormikState<Values> {
/** Form values */
values: Values;
/** map of field names to specific error for that field */
errors: FormikErrors<Values>;
/** map of field names to whether the field has been touched */
touched: FormikTouched<Values>;
/** whether the form is currently submitting */
isSubmitting: boolean;
/** whether the form is currently validating (prior to submission) */
isValidating: boolean;
/** Top level status state, in case you need it */
status?: any;
/** Number of times user tried to submit the form */
submitCount: number;
}
/**
* Formik computed properties. These are read-only.
*/
export interface FormikComputedProps<Values> {
/** True if any input has been touched. False otherwise. */
readonly dirty: boolean;
/** True if state.errors is empty */
readonly isValid: boolean;
/** The initial values of the form */
readonly initialValues: Values;
/** The initial errors of the form */
readonly initialErrors: FormikErrors<Values>;
/** The initial visited fields of the form */
readonly initialTouched: FormikTouched<Values>;
/** The initial status of the form */
readonly initialStatus?: any;
}
/**
* Formik state helpers
*/
export interface FormikHelpers<Values> {
/** Manually set top level status. */
setStatus: (status?: any) => void;
/** Manually set errors object */
setErrors: (errors: FormikErrors<Values>) => void;
/** Manually set isSubmitting */
setSubmitting: (isSubmitting: boolean) => void;
/** Manually set touched object */
setTouched: (touched: FormikTouched<Values>, shouldValidate?: boolean) => Promise<void | FormikErrors<Values>>;
/** Manually set values object */
setValues: (values: React.SetStateAction<Values>, shouldValidate?: boolean) => Promise<void | FormikErrors<Values>>;
/** Set value of form field directly */
setFieldValue: (field: string, value: any, shouldValidate?: boolean) => Promise<void | FormikErrors<Values>>;
/** Set error message of a form field directly */
setFieldError: (field: string, message: string | undefined) => void;
/** Set whether field has been touched directly */
setFieldTouched: (field: string, isTouched?: boolean, shouldValidate?: boolean) => Promise<void | FormikErrors<Values>>;
/** Validate form values */
validateForm: (values?: any) => Promise<FormikErrors<Values>>;
/** Validate field value */
validateField: (field: string) => Promise<void> | Promise<string | undefined>;
/** Reset form */
resetForm: (nextState?: Partial<FormikState<Values>>) => void;
/** Submit the form imperatively */
submitForm: () => Promise<void>;
/** Set Formik state, careful! */
setFormikState: (f: FormikState<Values> | ((prevState: FormikState<Values>) => FormikState<Values>), cb?: () => void) => void;
}
/**
* Formik form event handlers
*/
export interface FormikHandlers {
/** Form submit handler */
handleSubmit: (e?: React.FormEvent<HTMLFormElement>) => void;
/** Reset form event handler */
handleReset: (e?: React.SyntheticEvent<any>) => void;
handleBlur: {
/** Classic React blur handler, keyed by input name */
(e: React.FocusEvent<any>): void;
/** Preact-like linkState. Will return a handleBlur function. */
<T = string | any>(fieldOrEvent: T): T extends string ? (e: any) => void : void;
};
handleChange: {
/** Classic React change handler, keyed by input name */
(e: React.ChangeEvent<any>): void;
/** Preact-like linkState. Will return a handleChange function. */
<T = string | React.ChangeEvent<any>>(field: T): T extends React.ChangeEvent<any> ? void : (e: string | React.ChangeEvent<any>) => void;
};
getFieldProps: <Value = any>(props: string | FieldConfig<Value>) => FieldInputProps<Value>;
getFieldMeta: <Value>(name: string) => FieldMetaProps<Value>;
getFieldHelpers: <Value = any>(name: string) => FieldHelperProps<Value>;
}
/**
* Base formik configuration/props shared between the HoC and Component.
*/
export interface FormikSharedConfig<Props = {}> {
/** Tells Formik to validate the form on each input's onChange event */
validateOnChange?: boolean;
/** Tells Formik to validate the form on each input's onBlur event */
validateOnBlur?: boolean;
/** Tells Formik to validate upon mount */
validateOnMount?: boolean;
/** Tell Formik if initial form values are valid or not on first render */
isInitialValid?: boolean | ((props: Props) => boolean);
/** Should Formik reset the form when new initialValues change */
enableReinitialize?: boolean;
}
/**
* <Formik /> props
*/
export interface FormikConfig<Values> extends FormikSharedConfig {
/**
* Form component to render
*/
component?: React.ComponentType<FormikProps<Values>>;
/**
* Render prop (works like React router's <Route render={props =>} />)
* @deprecated
*/
render?: (props: FormikProps<Values>) => React.ReactNode;
/**
* React children or child render callback
*/
children?: ((props: FormikProps<Values>) => React.ReactNode) | React.ReactNode;
/**
* Initial values of the form
*/
initialValues: Values;
/**
* Initial status
*/
initialStatus?: any;
/** Initial object map of field names to specific error for that field */
initialErrors?: FormikErrors<Values>;
/** Initial object map of field names to whether the field has been touched */
initialTouched?: FormikTouched<Values>;
/**
* Reset handler
*/
onReset?: (values: Values, formikHelpers: FormikHelpers<Values>) => void;
/**
* Submission handler
*/
onSubmit: (values: Values, formikHelpers: FormikHelpers<Values>) => void | Promise<any>;
/**
* A Yup Schema or a function that returns a Yup schema
*/
validationSchema?: any | (() => any);
/**
* Validation function. Must return an error object or promise that
* throws an error object where that object keys map to corresponding value.
*/
validate?: (values: Values) => void | object | Promise<FormikErrors<Values>>;
/** Inner ref */
innerRef?: React.Ref<FormikProps<Values>>;
}
/**
* State, handlers, and helpers made available to form component or render prop
* of <Formik/>.
*/
export type FormikProps<Values> = FormikSharedConfig & FormikState<Values> & FormikHelpers<Values> & FormikHandlers & FormikComputedProps<Values> & FormikRegistration & {
submitForm: () => Promise<any>;
};
/** Internal Formik registration methods that get passed down as props */
export interface FormikRegistration {
registerField: (name: string, fns: {
validate?: FieldValidator;
}) => void;
unregisterField: (name: string) => void;
}
/**
* State, handlers, and helpers made available to Formik's primitive components through context.
*/
export type FormikContextType<Values> = FormikProps<Values> & Pick<FormikConfig<Values>, 'validate' | 'validationSchema'>;
export interface SharedRenderProps<T> {
/**
* Field component to render. Can either be a string like 'select' or a component.
*/
component?: keyof React.JSX.IntrinsicElements | React.ComponentType<T | void>;
/**
* Render prop (works like React router's <Route render={props =>} />)
*/
render?: (props: T) => React.ReactNode;
/**
* Children render function <Field name>{props => ...}</Field>)
*/
children?: (props: T) => React.ReactNode;
}
export type GenericFieldHTMLAttributes = React.JSX.IntrinsicElements['input'] | React.JSX.IntrinsicElements['select'] | React.JSX.IntrinsicElements['textarea'];
/** Field metadata */
export interface FieldMetaProps<Value> {
/** Value of the field */
value: Value;
/** Error message of the field */
error?: string;
/** Has the field been visited? */
touched: boolean;
/** Initial value of the field */
initialValue?: Value;
/** Initial touched state of the field */
initialTouched: boolean;
/** Initial error message of the field */
initialError?: string;
}
/** 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) => Promise<void | FormikErrors<Value>>;
/** Set the field's touched value */
setTouched: (value: boolean, shouldValidate?: boolean) => Promise<void | FormikErrors<Value>>;
/** Set the field's error value */
setError: (value: string | undefined) => void;
}
/** Field input value, name, and event handlers */
export interface FieldInputProps<Value> {
/** Value of the field */
value: Value;
/** Name of the field */
name: string;
/** Multiple select? */
multiple?: boolean;
/** Is the field checked? */
checked?: boolean;
/** Change event handler */
onChange: FormikHandlers['handleChange'];
/** Blur event handler */
onBlur: FormikHandlers['handleBlur'];
}
export type FieldValidator = (value: any) => string | void | Promise<string | void>;