Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Main tutorial is confusing and some parts are broken (getFieldProps) #2511

Open
jdahdah opened this issue Jun 6, 2020 · 4 comments
Open

Comments

@jdahdah
Copy link

jdahdah commented Jun 6, 2020

📖 Documentation

I'm working through the main tutorial on the Formik website, trying to understand how it works. The flow is good initially and it helps me to understand how Formik makes life easier, up until you reach the section about getFieldProps. It does not seem to be working correctly, and a number of features that the code examples did correctly in previous steps just stopped working. This issue is not meant as a complaint, but to point out the perspective of a first time user. I genuinely don't know how to proceed now, apart from moving on to the next step and hoping that code works.

Problems:

  1. Input fields lose their type, and thus their styling. I've added those in but it doesn't solve the next issue.
  2. Validation is broken. Apart from showing that a field is required, features like checking for the correct character count or the pattern of an email address are no longer working. It just says "Required".
  3. If you console.log('getFieldProps('firstName'), it does not seem to return the object that the migration docs suggests it returns (see After: screenshot below, the error is only due to logging and can probably (?) be ignored)
  4. The tutorial uses useFormik even though the docs state that you're not supposed to use it. I understand that the tutorial goes on to recommend using <Formik> but it feels like mixed messaging to introduce a hook that's only for advanced use right at the beginning of the learning journey. Just a minor issue unrelated to the other problems, but worth mentioning because it can be confusing to beginners.

Before:
validation before

After:
CleanShot 2020-06-06 at 17 52 51@2x

How to reproduce:

For the before state, replace the code in the Starter CodeSandbox with the example in the previous step, Schema Validation with Yup.
For the after state, paste the code from the next step, getFieldProps.

You can also just try this CodeSandbox which has code identical to the tutorial, plus that one console.log().

I'm happy to open a PR to add the missing type attribute, but I don't know how to fix the other issues. Perhaps someone could help me to understand getFieldProps better? The only other mention of it is in the migration docs which does not really go into how it works, and as mentioned above, appears to return something different than the docs state.

@hrgui
Copy link

hrgui commented Jun 7, 2020

  1. getFieldProps does not return type, as seen in https://jaredpalmer.com/formik/docs/migrating-v2#getfieldpropsnameorprops and https://github.com/jaredpalmer/formik/blob/master/packages/formik/src/Formik.tsx#L901-L940. We can't return type because formik does not about what type the form is going to look like (is it a checkbox, date, radio, text?). Example is email: when developing an email input, we'd want to use type=email instead of type=text.
  2. is because the formik version installed is v2.0.1.rc.13.... updating all the dependencies fixes it. See fixed example: https://codesandbox.io/s/formik-v2-tutorial-start-932fn. This is because in the version installed, getFieldProps returned [form, field] or something like that, which is not spreadable. Other note is that there is an error in the example codesandbox (0 is not an attribute of input).
  3. See number 2
  4. Yes, I find that confusing too.
  • useFormik itself is a ok API when trying to make simple forms with the cost of boilerplate. Note that useFormik doesnt work with the rest of the APIs that Formik provides (useField, ErrorMessage, ...).
  • <Formik /> removes the boilerplate, but at the cost of performance if there are too many components, or a render tree is expensive. This is because it uses React Context, which means that 1 field change / blur triggers all fields to change. This can be mitigated by using FastField instead.

Tip on debugging formik forms that I find useful:

Print out values. If values do not update on any Field or input change, the input is not hooked up properly. Check the hookup to the Input component. In this case, it is formik.getFieldProps.

@jdahdah
Copy link
Author

jdahdah commented Jun 9, 2020

@hrgui Thank you for answering all of my points in detail, I really appreciate it.

It sounds like the quickest way to fix this and remove confusion for newcomers is to:

  1. update the Starter CodeSandbox that the tutorial recommends to use the latest dependencies
  2. update the code samples in the tutorial to keep the type attributes.

I'll create a PR for task no. 2, but for task no. 1 I assume that @jaredpalmer would prefer to use a CodeSandbox saved under his own username for the official documentation?

@Johnrobmiller
Copy link

  1. getFieldProps does not return type, as seen in https://jaredpalmer.com/formik/docs/migrating-v2#getfieldpropsnameorprops and https://github.com/jaredpalmer/formik/blob/master/packages/formik/src/Formik.tsx#L901-L940. We can't return type because formik does not about what type the form is going to look like (is it a checkbox, date, radio, text?). Example is email: when developing an email input, we'd want to use type=email instead of type=text.
  2. is because the formik version installed is v2.0.1.rc.13.... updating all the dependencies fixes it. See fixed example: https://codesandbox.io/s/formik-v2-tutorial-start-932fn. This is because in the version installed, getFieldProps returned [form, field] or something like that, which is not spreadable. Other note is that there is an error in the example codesandbox (0 is not an attribute of input).
  3. See number 2
  4. Yes, I find that confusing too.
  • useFormik itself is a ok API when trying to make simple forms with the cost of boilerplate. Note that useFormik doesnt work with the rest of the APIs that Formik provides (useField, ErrorMessage, ...).
  • <Formik /> removes the boilerplate, but at the cost of performance if there are too many components, or a render tree is expensive. This is because it uses React Context, which means that 1 field change / blur triggers all fields to change. This can be mitigated by using FastField instead.

Tip on debugging formik forms that I find useful:

Print out values. If values do not update on any Field or input change, the input is not hooked up properly. Check the hookup to the Input component. In this case, it is formik.getFieldProps.

Not a very helpful answer. It states what the problem is very well, but then provides no solutions.

@johnrom
Copy link
Collaborator

johnrom commented Nov 18, 2021

The tutorial is essentially backwards. It's supposed to be demonstrating "look how easy Formik makes this by putting all this complex logic into these small boilerplate-free components", but it's not clear about it. You shouldn't start with useFormik, you should start with the base components Formik, Field etc, which is the example at the end of the tutorial (what the tutorial is supposed to lead you to). Use the "boilerplate-free" version until you know why you need to dig deeper into the components that Formik provides. At that point, you can learn just what you need for the specific hook that you need (useField, useFormik + FormikProvider, etc).

The above performance concerns are going away with #3231, and I will rewrite the documentation to start boilerplate-free and then illustrate when to step out of the basic components.

<Formik /> removes the boilerplate, but at the cost of performance if there are too many components, or a render tree is expensive. This is because it uses React Context, which means that 1 field change / blur triggers all fields to change. This can be mitigated by using FastField instead.

It's true in v2, but useFormik also has performance issues in that it causes renders on every change to the parent component which require careful memoization at the root level. getFieldProps is not memoized. With the Formik component all of that rendering is scoped to the Formik component which is itself very light, and only becomes a major concern when using the <Formik>{(formik) => <etc />}</Formik> function-as-children method. I would avoid the function-as-children method at all costs except for quick prototypes. With many child components, it can indeed be very performance heavy, but that will go away with v3, and I wouldn't recommend optimizing before there is an issue.

In v3, I have done away with all of these concerns (except for function-as-children), and now useFormik, Formik and Field are highly optimized in #3231.

TL:DR; until I have a chance to formalize a release (I'm currently working on a documentation strategy to keep the docs up to date with real code and prevent these issues), I'd recommend using the base components Formik, FastField, Field, ErrorMessage, FieldArray until you know you need to dig deeper. True, the Fields don't have great performance, but it's generally not noticeable until you are rendering many fields, and that performance hit will go away with v3, which you can test at: @johnrom/[email protected]. If you do have many components, you should generally consider splitting the form up into pages for user experience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants