Avatar

Nǐ hǎo, I'm Julia.

React Formik and Yup Troubleshooting Tips

#forms #react #yup

4 min read

I’ve been spending the last couple of weeks reworking how we render forms in our React Native app. The main driver for this is a new feature we’re releasing soon, that requires over 150 questions to be asked to the user. In order to minimise code duplication and to make the editing of form questions easier going forward, we decided to go down the route of programmatically rendering the various forms and their questions from a large JSON file.

Rendering our forms this way also meant having to programmatically generate the required Yup validation object. As we’re going to be migrating users across from an older system, there’s also an element of certain forms having pre-filled existing data that needs validating.

So far, it all seems to be working out great, but there were some issues I can across during the build that I thought I’d note down. This is mostly for my future self as I’m sure I had come across some of these same issues in the past but had forgotten about them...so here’s to saving my future self some time. 😃

Issue: If your form is pre-populated with data and validation doesn’t work on component mount

  • Ensure you’ve set validateOnMount={true} within your Formik component props. Also, check that you haven’t included formikProps.dirty as an additional check to enable your submit button (which I may or may not have done, then wasted 30 minutes trying to figure out why my button continued to remain disabled). 😅
<Formik
  validateOnMount={true}
  initialValues={initialValues}
  onSubmit={onSubmit}
  validationSchema={validationSchema}
  ...
>
 {(formikProps) => {
  return (
    <Form...

Issue: Not all field validations are working as expected

  • Check that you’ve initialised each field value to at least an empty string, otherwise Yup will not know that the field(s) exists and will not be able to validate it.
  • For context, I had some conditional fields that were only required if certain criteria were met. These fields were being ignored, because they were not initialised when the form component was mounted.

Issue: How to access formikProps outside the form component

There are a few ways of doing this depending on what specifically you’re trying to achieve.

  • If you need to access formikProps within a child component of the form, you can either pass it down as a prop, or use the useFormikContext() hook.
  • If you need to access formikProps at the form component level, but outside the render method, create a React ref and use the innerRef Formik property to reference your form (and access the Formik methods).
export const MyForm = () => {

  const formRef = useRef(null);

  const handleSubmit = () => {
    if (formRef.current) {
      formRef.current.handleSubmit()
    }
  }

  return (
    <Formik
      validateOnMount={true}
      innerRef={formRef}
      initialValues={initialValues}
      onSubmit={onSubmit}
      validationSchema={validationSchema}
      ...
    >
    // ...
  )
}

Issue: Using React lifecycle hooks that are dependent on formikProps

For context, the issue I was faced with was how to check when a user had filled in specific form fields and moved on to the next question (for animation purposes). A solution I came up with was to utilise the useEffect hook to check if my requirement passed, whenever the formikProps.values array had been updated.

I was using ES6 arrow function syntax, and was getting an error when I tried to do this:

<Formik
  ...
>
  {(formikProps) => {

    React.useEffect(() => {
      updateQuestionsState(formikProps);
    });

    return (
      <Form...

    )
  }}
</Formik>

To fix the error, I subbed out the arrow function with a named function:

<Formik
  ...
>
  {function FormWithUseEffect(formikProps) {

    React.useEffect(() => {
      updateQuestionsState(formikProps);
    });

    return (
      <Form ...

    )
  }}
</Formik>

© 2016-2024 Julia Tan · Powered by Next JS.