formik
formik copied to clipboard
Support custom fields without workarounds
Feature request
Current Behavior
This is the interface of Formik's handle change:
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;
};
The Field's Value
can be any
like here:
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'];
}
Just HTML <input>
tag produces React.ChangeEvent
what means that Formik cannot be attached with its handleChange
function to a custom field which does not produce it.
The error in the browser when I use it with e.g. boolean
is:
Uncaught TypeError: Cannot read properties of undefined (reading 'type')
at formik.esm.js:721:1
at formik.esm.js:755:1
at formik.esm.js:1256:1
at n (project44-manifest-ds.js:2:48822)
at project44-manifest-ds.js:2:49089
at Object.setSelected (project44-manifest-ds.js:2:222034)
at onChange (project44-manifest-ds.js:2:221812)
at Object.vi (react-dom.production.min.js:202:330)
at ui (react-dom.production.min.js:32:27)
at xi (react-dom.production.min.js:32:81)
and it happens at this line:
https://github.com/jaredpalmer/formik/blob/b9cc2536a1edb9f2d69c4cd20ecf4fa0f8059ade/packages/formik/src/Formik.tsx#L611
Workaround which I currently use is:
const { values, setFieldValue } = useFormikContext<SearchFormProps>();
const [field, meta] = useField<string>('test');
return (
<CheckboxField
isSelected={field.value}
// onChange here has signature of `(value: boolean) => void`
onChange={(value) => {
setFieldValue(field.name, value);
}}
....
Desired Behavior
A boolean should be possible to save with handleChange
so I may not use the workaround.
Suggested Solution
Please support signature
handleChange: <Value>(field: Value | React.ChangeEvent<any>) => void
How to do it?
Instead of if (!isString(eventOrTextValue))
check here
https://github.com/jaredpalmer/formik/blob/b9cc2536a1edb9f2d69c4cd20ecf4fa0f8059ade/packages/formik/src/Formik.tsx#L600
this could be used:
function isChangeEvent<T extends HTMLElement = HTMLElement>(
eventOrValue: ChangeEvent<T> | unknown,
): eventOrValue is ChangeEvent<T> {
return (eventOrValue as ChangeEvent<T>).target !== undefined;
}
Who does this impact? Who is this for?
- Devs who write custom components without
<input>
tag - devs who use component libraries which does not expose
onChange
prop with(event: ChangeEvent) => void
signature, and exposeonChange
prop with<T>(val: T) => void
signature
Describe alternatives you've considered
The workaround is the alternative.
Additional context
Noting