jaredpalmer / formik

Build forms in React, without the tears šŸ˜­
https://formik.org
Apache License 2.0
33.99k stars 2.79k forks source link

Field: Pass metas to component #3091

Open lucien-perouze-cezembre opened 3 years ago

lucien-perouze-cezembre commented 3 years ago

Feature request

Current Behavior

When using prop component on Field the meta prop is not pass down. Even so it is mentioned in docs. If you pass a functional component as a child you have to specify every child and it's redondant. Props spreading is a bad practice : react/jsx-props-no-spreading

Desired Behavior

It would be great to have that meta prop inside components fields.

Suggested Solution

There is a comment in the code that says that meta prop is not passed for backward compatibility purposes. I guess it's to avoid potential overriding for people who used a custom 'meta' props in their code. I think that in the first place they used a custom meta prop to solve this issue. I would recommend to check if a meta prop already exists and if not pass it.

Who does this impact? Who is this for?

Everybody. it is a better pattern to abstract all inputs inside custom fields (input, select, checkbox, ...). That way you can include labels, error, warnings, etc... into the custom component and so reuse between forms instead of rewriting the same input everywhere. I would recommend everybody to do so.

Describe alternatives you've considered

I considered adding the feature myself but I have no idea how to test it locally.

Additional context

I just switched from redux-form. I really want to use this library but this is very frustrating for me. Thank you for all the work you've done anyway. Hope you'll find time for this :)

github-actions[bot] commented 3 years ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 60 days

johnrom commented 3 years ago

Can you use <Field as={YourComponent} />? That receives meta.

lucien-perouze-cezembre commented 3 years ago

Can you use <Field as={YourComponent} />? That receives meta.

No, that way metas are not passed down to the component YourComponent.

It is explicitly written that way here : https://github.com/formium/formik/blob/6d2fce73138ff00f29bd7227bd0aa38752b89878/packages/formik/src/Field.tsx#L203

I guess it is for people that already use meta as props for other purposes but it is quite annoying.

I would suggest to pass it anyway or at least with another safe name like formikMeta

johnrom commented 3 years ago

Ah you're right that doesn't get meta either. v3 will expose a hook called useFieldMeta.

I'm not sure the specifics of why these don't accept meta. I generally use hooks like useField instead.

mikoz93 commented 3 years ago

I'm not sure the specifics of why these don't accept meta. I generally use hooks like useField instead.

A comment in the source file says it's for backwards compatibility reasons, but that doesn't make much sense, as it's just an extra property that the consumer can choose to use or not use. It is a little inconvenient to have to do form.getFieldMeta(name) when it could've just been provided to start with.

johnrom commented 3 years ago

if a third party or userland component expects a meta prop that isn't Formik's, passed from a form, through Field, and down to it, adding this prop would break that functionality. That's the only reason I can think of that it wouldn't be present here. However, I don't know as I didn't write it. Component was the first version used for custom components, so it would have the longest and most varying usages.

I generally wrap Field with like NumberField which then makes a simple call to Field as an Input element, instead of calling Field as={} or Field component= because the moment I tend to apply common functionality to field generally will be validate={}, or parse={} or format={} in the case of v3. Plus, then I don't have a million references to Formik, just one for each Field, so if in the future I change libraries I can just change those connections.

mikoz93 commented 3 years ago

I generally wrap Field with like NumberField which then makes a simple call to Field as an Input element, instead of calling Field as={} or Field component=

I do the opposite actually, I pass my custom fields (TextField, DateField, SelectField, etc...) to a Field or FastField. This allows me to decide if I need the field optimised or not on the form by form basis.

Speaking of v3, is there a plan to add an "onChange" type of prop to a field? I've seen it being requested a few times. This currently requires a use of useEffect which feel hacky or some other custom implementations.

johnrom commented 3 years ago

FastField isn't necessary in v3 because fields only subscribe to their slice of state.

At that point it could simply be a boolean prop passed to Field like updateOnBlur.

In terms of the onChange functionality, there is a bit of complexity there due to the fact that fields can be updated programmatically. Using an effect really ends up being the place to capture this state change from wherever it is updated.

The other place to capture that would be decorating the reducer itself, which is something I briefly discuss under the issue "Formik Plugins"

github-actions[bot] commented 3 years ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 60 days

github-actions[bot] commented 3 years ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 60 days