jaredpalmer / formik

Build forms in React, without the tears 😭
https://formik.org
Apache License 2.0
33.98k stars 2.79k forks source link

TypeError: Cannot read property 'validate' of undefined #2291

Open stephanie-saretsky opened 4 years ago

stephanie-saretsky commented 4 years ago

❓Question

I am getting the error TypeError: Cannot read property 'validate' of undefined when running a chai-enzyme test, followed by the warning: console.warn node_modules/tiny-warning/dist/tiny-warning.cjs.js:13 Warning: Formik context is undefined, please verify you are calling useFormikContext() as child of a <Formik> component.

Any help would be appreciated, I've also posted in the Discord channel but some other people had the same question but no response, so I thought I'd open an issue since it was easier to post more code here. Thanks!

This is the render of my formik component:


    const { formInfo, children, validationSchema, bindSubmitForm } = this.props;
    const validation = Yup.object(validationSchema);
    return (
      <Formik
        initialValues={formInfo}
        /* tslint:disable-next-line:jsx-no-lambda jsx-no-multiline-js */
        onSubmit={() => {
        }} // onSubmit is a required prop for Formik to work but we use our own submit in the parent component
        validationSchema={validation}
      >
        {/* tslint:disable-next-line:jsx-no-multiline-js */}
        {(formik) => {
          bindSubmitForm(formik.submitForm);
          return (
            <div className="common-form-page-container">
              <div className="common-form-container">
                <Form translate={'yes'}>
                  {children(formik)}
                </Form>
              </div>
            </div>
          );
        }}
      </Formik>
    );
  }
}

CarouselInput is the component I am testing:
formTemplate = (formik) => {
    const { banner, bannerIndex } = this.state;
    return(
      <React.Fragment>
        <FormSection title="Write It">
          <FormRow>
            <FormColumn>
              <FormInput
                required={false}
                field="carousel"
                formType={HTML_TAGS.CUSTOM}
                /* tslint:disable-next-line:jsx-no-lambda jsx-no-multiline-js */
                render={() => {
                  const handleContentIndex = async (index) => {
                    this.setState({
                      bannerIndex: index,
                    });
                  };
                  return (
                    <CarouselInput
                      formInfo={banner.content}
                      onChange={this.handleOnChange}
                      newItem={this.addNewTab}
                      handleIndex={handleContentIndex}
                      carouselSlideIndex={bannerIndex}
                      children={(onChange, content) => <BannerCarouselForm onChange={onChange} content={content} />}
                    />
                  );
                }}
              />
            </FormColumn>
          </FormRow>
        </FormSection> 
  </React.Fragment>
)}

And this is the test:
  it('should add new slide on click', () => {
    const tree = shallow(<CommonFormWrapper />);

    const component = mount(
      <CarouselInput
        formInfo={content}
        onChange={this.handleOnChange}
        newItem={this.addNewTab}
        handleIndex={handleIndex}
        carouselSlideIndex={0}
        /* tslint:disable-next-line:jsx-no-lambda */
        children={(onChange, content) => <BannerCarouselForm onChange={onChange} content={content} />}
      />
    );
    tree.find(component).dive().find('.add-slide-button').simulate('click', { persist: () => {}, });
    expect(newItem).to.have.been.calledOnce;
  });
TotallWAR commented 4 years ago

I have the same problem. But it happens when i manually execute validateField function. Did you find solution?

zsid commented 4 years ago

I have that issue when I extract a component and test it on its own. In my case I am using FieldArray and I get that error. It is fixed when I have Formik acting as a wrapper as if it is part of the actual form.

Badyanchik commented 4 years ago

I use useFormik hook. My validation schema is valid, but I have the same problem when I call validateField manually.

vitorlimadev commented 4 years ago

Having the same issue on latest version of Formik.

k290 commented 4 years ago

Having the same issue

johnrom commented 4 years ago

It seems like in most cases, the Form Fields aren't being wrapped in a FormikProvider (like <Formik />) when testing.

@Badyanchik validateField is kind of interesting. Basically, you'd still need to wrap a <Field /> in a <FormikProvider /> in order to register the field with Formik's fieldRegistry and instantiate the field-level validation callback. You might be able to get away with manually calling formik.registerField, but Formik relies heavily on Context so you may run into other issues if you try to circumvent context.

That said, any and all codesandbox repros are welcome so I can look closer at these issues!

resting commented 4 years ago

I'm using react native's TextInput got the same error with I tried to call validateField(). Probably because there's not <Field> wrapped?

johnrom commented 4 years ago

Formik component or another FormikContext provider must appear above your useField hook or Field component in the component hierarchy, even when testing.

If you're using useField, you don't need Field, but you still need Formik.

GuppuBoss commented 4 years ago

I am also getting same error when using validateField() So, for the time being i am using validateForm()

jvitorr commented 4 years ago

Same error

johnrom commented 4 years ago

@jvitorr did you try https://github.com/jaredpalmer/formik/issues/2291#issuecomment-619577563 ?

owystyle commented 4 years ago

Instead of validateField() you can use setFieldTouched() which can also trigger validation

abhishekg-cashify commented 3 years ago

I have solve this by putting ref={this.formRef} in form tag, formRef = React.createRef() i have use in class

CharlieBellow commented 1 year ago

I have the same problem. but I'm using the < Formik > and < Form > tags when the validation scheme is added the form stops sending the values

thuansilva commented 1 year ago

When i uses tag , I use Field-level validation with validate name property.

See more in: docs

       const validation = Yup.object(validationSchema);
       return (
           <Formik  validate={validation}/>
        )
pooooriya commented 1 year ago

<FormikProvider value={formik}> </FormikProvider>

you need wrap everything inside this and pass const formik = useFormik(); to it