formik icon indicating copy to clipboard operation
formik copied to clipboard

isValid is false although all fields are valid

Open burtek opened this issue 6 years ago • 17 comments

🐛 Bug report

Current Behavior

According to validation reference FAQ returning undefined as error message is considered as marking field valid. Yet returning { fieldName: undefined } from validation function sets isValid tofalse thus preventing form from submitting. This is caused by following line in code:

https://github.com/jaredpalmer/formik/blob/85d15b302cd776eb615064a4451e1a7575b1439d/src/Formik.tsx#L425

Expected behavior

Returning { fieldName: undefined } from validation function should set isValid to true

Reproducible example

https://codesandbox.io/s/py95r24n7x

Typing anything in the field changes form state, but keeps isValid set to false

If you change validate to const validate = values => ({});, isValid will be set to true

Suggested solution(s)

At least change the docs. To make the validation work according to current docs, you'd need to check all values (incl. nested values) in object returned by validation function.

Your environment

Software Version(s)
Formik 1.3.2

burtek avatar Nov 18 '18 16:11 burtek

The documentation is pretty weird around that line. This is the code that decides whether you have errors. Object.keys(this.state.errors).length - this snippet pretty much means that any set field (even with undefined) will result in isValid being false.

I recommend clearing your own object of any undefined properties before returning the validation errors to formik. This could work before returning -

Object.keys(errors)
	.filter(key => errors[key] !== undefined)
	.reduce((res, key) => {
		res[key] = errors[key];
		return res;
	}, {})

motiazu avatar Nov 25 '18 07:11 motiazu

An issue relating to isValid, not sure if I should start a new issue.

I noticed that the isValid field stays false after submitting a form if the values are set using initialvalues. If the onChange is triggered, then the isValid will be correct.

https://codesandbox.io/s/302vp2wqxq

Example

webberwang avatar Dec 30 '18 01:12 webberwang

@webberwang I ran into the same issue, but then found https://jaredpalmer.com/formik/docs/api/formik#isinitialvalid-boolean

barrett-vegas-com avatar Jan 07 '19 17:01 barrett-vegas-com

@webberwang This seems be to work for me. Using @barrett-vegas-com response with isInitialValid,

const validate = (values: Values): FormikErrors<Values> => { ... };
const isInitialValid = (values: FormikConfig<Values> & IProps) =>
  Object.keys(validate(values.initialValues)).length === 0;

withFormik({ ...  
 isInitialValid,
 validate
})

jp94 avatar Feb 15 '19 02:02 jp94

In case you are using yup

const isInitialValid = schema.isValidSync(initialValues);

emil-alexandrescu avatar Apr 25 '19 09:04 emil-alexandrescu

This has been addressed is #1410

jaredpalmer avatar Apr 26 '19 13:04 jaredpalmer

An issue relating to isValid, not sure if I should start a new issue.

I noticed that the isValid field stays false after submitting a form if the values are set using initialvalues. If the onChange is triggered, then the isValid will be correct.

https://codesandbox.io/s/302vp2wqxq

Example

put this inside <Formik/>

isInitialValid={true}

its working .. on Edit Form initial values always true....

suggested Link

https://jaredpalmer.com/formik/docs/api/formik#isinitialvalid-boolean

webpipl avatar Aug 13 '19 01:08 webpipl

Is there a way to set the is valid manually? When I set the field value from session storage and pass the same value to the initial values, the invalid is being set to true upon error though I trigger setFieldError.

vinodh99 avatar Aug 21 '19 03:08 vinodh99

@vinodh99 Try this:

const initialValues = {
... initial values
};
<Formik
  .... other props
  initialValues={initialValues}
  validationSchema={schema}
  isInitialValid={schema.isValidSync(initialValues)}
>
... rest of code
</ Formik>

rob10e avatar Sep 04 '19 15:09 rob10e

This issue has been fixed in 2.x only, 1.x versions has to use isInitialValid.

andrew-aladev avatar Oct 26 '20 12:10 andrew-aladev

I'm still having this issue. I'm using version 2.1.5 and even without any validation isValid is always false

pdancewicz avatar Nov 05 '20 11:11 pdancewicz

I'm still having this issue. I'm using version 2.1.5 and even without any validation isValid is always false

Have you managed to find a way around or a fix for this?

jrrewers avatar Nov 12 '20 14:11 jrrewers

Hello guys, I am using [email protected] and the following code works perfect:

<Formik
  initialValues={initialValues}
  validationSchema={schema}
  isInitialValid={() => schema.isValidSync(initialValues)}
  onSubmit={onSubmit}
  enableReinitialize
>
...

Please try with your projects.

andrew-aladev avatar Nov 12 '20 14:11 andrew-aladev

  isInitialValid={() => schema.isValidSync(initialValues)}

That works, thanks! But when I do isInitialValid={schema.isValidSync(initialValues)} it fails.

jrrewers avatar Nov 12 '20 15:11 jrrewers

I also needed the initial error object to be correct. I wrote this little helper for sync cases:

import { useMemo } from 'react'
import { FormikErrors, yupToFormErrors } from 'formik'
import { ObjectSchema } from 'yup'

export default function useInitialErrorsSync(
  schema: ObjectSchema,
  initialValues: any,
): [boolean, FormikErrors<any>] {
  const values: [boolean, FormikErrors<any>] = useMemo(() => {
    try {
      schema.validateSync(initialValues, { abortEarly: false })
    } catch (err) {
      if (err.name === 'ValidationError') return [false, yupToFormErrors(err)]
    }
    return [true, {}]
  }, [])
  return values
}

can be used like

  ...
  const [isInitialValid, initialErrors] = useInitialErrorsSync(schema, initialValues)
  return <Formik
                  validateOnChange
                  validateOnBlur
                  validateOnMount
                  validationSchema={schema}
                  isInitialValid={isInitialValid}
                  initialErrors={initialErrors}
                  initialValues={initialValues}
                  onSubmit={onSubmit}
                >
   ...

quorak avatar May 04 '21 04:05 quorak

isInitialValid is deprecated and will be removed in formik soon, it is advised to use validateOnMount

EDMONDGIHOZO avatar Sep 08 '21 14:09 EDMONDGIHOZO

Hello guys, I am using [email protected] and the following code works perfect:

<Formik
  initialValues={initialValues}
  validationSchema={schema}
  isInitialValid={() => schema.isValidSync(initialValues)}
  onSubmit={onSubmit}
  enableReinitialize
>
...

Please try with your projects.

In my case enableReinitialize was the game changer.

maciej-wira avatar Aug 11 '22 14:08 maciej-wira