Aximili
Aximili

Reputation: 29484

Rendering Formik Field outside Formik form

We have our own input components (like Checkbox, Textbox, or even CurrencyInput component)

We are now using Formik. So we replaced all <input... with <Field... in our components, eg.

const Checkbox = (props) => {
  ...
  return (
    <div className={myClass1}>
      <Field type='checkbox' name={props.name} className={myClass2} ... />
      <label ...>{props.label}</label>
    </div>
  )
};

Now the problem is, we can't have a standalone Checkbox outside a form anymore (eg. for an on-screen-only option). It will throw:

this.props.formik.registerField is not a function

We feel this is a dealbreaker. But before we ditch Formik and write our own form validation logics, I wonder if anyone else are having this dependency issue.

Is there really no way of rendering Formik Field outside Formik?

Upvotes: 5

Views: 4193

Answers (1)

TLadd
TLadd

Reputation: 6884

The Field component is what connects a form field to the Formik state. It uses context under the hood; Formik is the context provider and Field is the context consumer. Field is tied to Formik and has no use outside of it. For your use case where you want to render form fields that are sometimes connected to Formik and sometimes not, I would export two different components:

  1. The base Checkbox component that has nothing to do with Formik. It should just use a normal input
  2. A Field wrapper around that Checkbox component

While the Field component can take a type, causing it to render the corresponding input, it can also take a render prop to render whatever you want, and it is passed all of the state Formik manages for that field.

For example, your Checkbox and CheckboxField components could looks something like this:

const Checkbox = (props) => {
  ...
  return (
    <div className={myClass1}>
      <input type='checkbox' checked={props.checked} onChange={props.onChange} />
      <label ...>{props.label}</label>
    </div>
  )
};

const CheckboxField = (props) => {
  return (
    <Field name={props.name}>
      {(field) => <Checkbox label={props.label} {...field} />}
    </Field>
  )
}

Now you use have two components that render exactly the same, but one is meant to be used within a Formik form (CheckboxField) and the other can be used anywhere (Checkbox).

Upvotes: 10

Related Questions