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

Cannot read property 'values' of undefined #4

Open
pgrekovich opened this issue May 17, 2018 · 18 comments
Open

Cannot read property 'values' of undefined #4

pgrekovich opened this issue May 17, 2018 · 18 comments

Comments

@pgrekovich
Copy link

One of these days there was this error. Any idea what might be the problem?

screenshot_3

@latviancoder
Copy link

latviancoder commented Jun 8, 2018

formik is using new Provider/Consumer from react 16.3, while this library still relies on old context api.

@jaredpalmer are you planning on updating this?

@maticrivo
Copy link

@jaredpalmer any update or plans on this?

@pgrekovich
Copy link
Author

@maticrivo I had spent time to understand it, and in real life, you don't need it! Try to use componentDidUpdate if you need to update something after the form has updated.

@maticrivo
Copy link

@pgrekovich componentDidUpdate will only work if I use formik as an HOC with withFormik but i use formik with a render prop

@NamPNQ
Copy link

NamPNQ commented Aug 3, 2018

Just use connect api
Here is my solution

// @flow
import React from 'react';
import { connect } from 'formik';

type Props = {
  onChange: Function,
  formik: Object,
};

class Effect extends React.Component<Props> {
  componentWillReceiveProps(nextProps) {
    const { values, touched, errors, isSubmitting } = this.props.formik;
    const {
      values: nextValues,
      touched: nextTouched,
      errors: nextErrors,
      isSubmitting: nextIsSubmitting,
    } = nextProps.formik;
    if (nextProps.formik !== this.props.formik) {
      this.props.onChange(
        {
          values,
          touched,
          errors,
          isSubmitting,
        },
        {
          values: nextValues,
          touched: nextTouched,
          errors: nextErrors,
          isSubmitting: nextIsSubmitting,
        },
      );
    }
  }

  // eslint-disable-next-line
  render() {
    return null;
  }
}

export default connect(Effect);

@sreeram-muddu
Copy link

@jaredpalmer any update on this issue?

@luke-dare
Copy link

Hey .. I've got the same issue.

@h0jeZvgoxFepBQ2C
Copy link

@jaredpalmer ping, same issue here

@brandonhall
Copy link

brandonhall commented Dec 13, 2018

My solution was very similar to @NamPNQ and works great for us:

import { Component } from 'react';
import { debounce, isEqual } from 'lodash';
import { connect, FormikValues, FormikProps } from 'formik';

interface IProps {
  onChange: (values: FormikValues) => void;
}

interface IPropsEnhanced extends IProps {
  formik: FormikProps<FormikValues>;
}

const SAVE_DELAY = 1000;

class FormikEffects extends Component<IPropsEnhanced> {
  onChange = debounce(this.props.onChange, SAVE_DELAY);

  componentDidUpdate(prevProps: IPropsEnhanced) {
    const { formik } = this.props;
    const { isValid } = formik;

    const hasChanged = !isEqual(prevProps.formik.values, formik.values);
    const shouldCallback = isValid && hasChanged;

    if (shouldCallback) {
      this.onChange(formik.values);
    }
  }

  render() {
    return null as null;
  }
}

export default connect<IProps>(FormikEffects);

@Ridder90
Copy link

Ridder90 commented Mar 4, 2019

@brandonhall Thanks for sharing! Using your example gives me IProps is not defined. Did you define it somewhere else?

@brandonhall
Copy link

@Ridder90 No, it's defined at the top of the file as a TypeScript interface.

@Ridder90
Copy link

Ridder90 commented Mar 4, 2019

Hmmm strange...running it with export default connect(FormikEffects); works perfectly though.

@sebastianpatten
Copy link

Any eta when this will be fixed? I'm getting the same issue

@BrianBusby
Copy link

Same here; would love a fix for this

@aronkof
Copy link

aronkof commented May 1, 2019

Just use connect api
Here is my solution

// @flow
import React from 'react';
import { connect } from 'formik';

type Props = {
  onChange: Function,
  formik: Object,
};

class Effect extends React.Component<Props> {
  componentWillReceiveProps(nextProps) {
    const { values, touched, errors, isSubmitting } = this.props.formik;
    const {
      values: nextValues,
      touched: nextTouched,
      errors: nextErrors,
      isSubmitting: nextIsSubmitting,
    } = nextProps.formik;
    if (nextProps.formik !== this.props.formik) {
      this.props.onChange(
        {
          values,
          touched,
          errors,
          isSubmitting,
        },
        {
          values: nextValues,
          touched: nextTouched,
          errors: nextErrors,
          isSubmitting: nextIsSubmitting,
        },
      );
    }
  }

  // eslint-disable-next-line
  render() {
    return null;
  }
}

export default connect(Effect);

Thanks, it works as expected :)

@leechingching
Copy link

My solution was very similar to @NamPNQ and works great for us:

import { Component } from 'react';
import { debounce, isEqual } from 'lodash';
import { connect, FormikValues, FormikProps } from 'formik';

interface IProps {
  onChange: (values: FormikValues) => void;
}

interface IPropsEnhanced extends IProps {
  formik: FormikProps<FormikValues>;
}

const SAVE_DELAY = 1000;

class FormikEffects extends Component<IPropsEnhanced> {
  onChange = debounce(this.props.onChange, SAVE_DELAY);

  componentDidUpdate(prevProps: IPropsEnhanced) {
    const { formik } = this.props;
    const { isValid } = formik;

    const hasChanged = !isEqual(prevProps.formik.values, formik.values);
    const shouldCallback = isValid && hasChanged;

    if (shouldCallback) {
      this.onChange(formik.values);
    }
  }

  render() {
    return null as null;
  }
}

export default connect<IProps>(FormikEffects);

It works as expected, but the console shows the warming below

react-dom.development.js:506 Warning: A component is changing an uncontrolled input of type undefined to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://fb.me/react-controlled-components

Do you have any ideas how to solve it ?

@NamPNQ
Copy link

NamPNQ commented Jul 23, 2019

@leechingching it's not related with this issue, you can check the guide in https://fb.me/react-controlled-components, may be your component dont set value back in input

@jariz
Copy link

jariz commented Oct 18, 2019

Here's my version recreating formik-effect with hooks in 11 lines.
See here for TS version.

import { connect } from 'formik';
import { useEffect, useRef } from 'react';
const Effect = ({ formik, onChange }) => {
    const ref = useRef(null);
    useEffect(() => {
        onChange(formik, ref.current);
        ref.current = formik;
    }, [formik]);
    return null;
};
export default connect(Effect);

jariz added a commit to jariz-forks/formik-effect that referenced this issue Oct 18, 2019
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