[v2] Improve Formik.executeChange to accept not only string or event
See original GitHub issue🚀 Feature request
I’m trying to use useField
hook to connect formik to custom component:
My custom component uses objects as a value:
const CustomComponent = ({ value, onChange }) => (
<button onClick={() => onChange({ some: 'value' })}>{value.some}</button>
)
Current Behavior
I’m getting Cannot read property 'type' of undefined
error when I connect my custom component to formik like this:
const FormikCustomComponent = (props) => {
const [field] = useField(props.name);
return (
<CustomComponent {...props} {...field} />
);
};
Error appears when button is clicked (when onChange
callback is called). Error thrown because my CustomComponent
sends to onChange
object instead of string or event. Formik.executeChange
checks if passed value is string (it is not) and tries to treat it as an event (and of course fails).
Desired Behavior
Add ability to pass to onChange
callback any desired value and use it “as is”. executeChange
should try to parse value ONLY when EVENT is passed as a value.
Suggested Solution
Currently we check if eventOrTextValue
is string, and if it is not a string, we treat it as event.
(https://github.com/jaredpalmer/formik/blob/master/src/Formik.tsx#L505)
My suggestion is to check if value is EVENT instead of string. If event is passed, then, you need to run code to extract value from the event. In other cases just use passed value “as is”
Example solution:
const executeChange = React.useCallback(
(eventOrTextValue: any | React.ChangeEvent<any>, maybePath?: string) => {
let field = maybePath;
let val = eventOrTextValue;
let parsed;
// If the first argument is a synthetic React Event or a real Dom Event,
// we handle like we would a normal HTML change event.
if (eventOrTextValue && (eventOrTextValue instanceof Event || eventOrTextValue.nativeEvent instanceof Event)) {
// no changes here ...
}
// no changes here...
},
[setFieldValue, state.values]
);
Possible workarounds
Of course, I’m able to JSON.stringify
value before passing it to onChange
and JSON.parse
it back in component to be able to work with any type of value, but I think it is not a good idea…
Who does this impact? Who is this for?
It will make much easier to connect formik to custom component that works with objects / arrays as a value.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:20
- Comments:11 (2 by maintainers)
Top GitHub Comments
If somebody is looking for working workaround, here it is. It’s an universal formk field component, that works both with native and custom fields:
This component is not optimised and will force re-render on every formik context change, so use it only in small or medium forms.
Usage example:
I checked source code one more time and found that my suggested solution will not work well, because
field.onChange
is not bound tofield.name
.When event is passed to
onChange
formik gets field name fromevent.target.name
. When string is passed toonChange
formik uses this string asfield.name
and returnsevent => executeChange(event, field.name)
, so we need to callonChange(name)(value)
instead of justonChange(value)
.So, currently I have 2 suggestions:
field.onChange
tofield.name
passed touseField
executeChange
to check if passed value is EVENT (see example above)