Skip to content

Commit

Permalink
fix(formik)!: validateOnMount initialize isValid to false until valid…
Browse files Browse the repository at this point in the history
…ation performed
  • Loading branch information
anonkey committed Aug 26, 2024
1 parent c798145 commit 33818d3
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/sour-cats-rescue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'formik': major
---

validateOnMount initialize isValid to false until validation performed
23 changes: 14 additions & 9 deletions packages/formik/src/Formik.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ export function useFormik<Values extends FormikValues = FormikValues>({
const initialTouched = React.useRef(props.initialTouched || emptyTouched);
const initialStatus = React.useRef(props.initialStatus);
const isMounted = React.useRef<boolean>(false);
const validated = React.useRef<boolean>(false);
const fieldRegistry = React.useRef<FieldRegistry>({});
if (__DEV__) {
// eslint-disable-next-line react-hooks/rules-of-hooks
Expand Down Expand Up @@ -314,6 +315,7 @@ export function useFormik<Values extends FormikValues = FormikValues>({
props.validationSchema ? runValidationSchema(values) : {},
props.validate ? runValidateHandler(values) : {},
]).then(([fieldErrors, schemaErrors, validateErrors]) => {
validated.current = true;
const combinedErrors = deepmerge.all<FormikErrors<Values>>(
[fieldErrors, schemaErrors, validateErrors],
{ arrayMerge }
Expand Down Expand Up @@ -949,15 +951,18 @@ export function useFormik<Values extends FormikValues = FormikValues>({
);

const isValid = React.useMemo(
() =>
typeof isInitialValid !== 'undefined'
? dirty
? state.errors && Object.keys(state.errors).length === 0
: isInitialValid !== false && isFunction(isInitialValid)
? (isInitialValid as (props: FormikConfig<Values>) => boolean)(props)
: (isInitialValid as boolean)
: state.errors && Object.keys(state.errors).length === 0,
[isInitialValid, dirty, state.errors, props]
() => {
if (!validated.current && validateOnMount) return false
if (typeof isInitialValid !== 'undefined') {
if (dirty) return state.errors && Object.keys(state.errors).length === 0;

return isInitialValid !== false && isFunction(isInitialValid)
? (isInitialValid as (props: FormikConfig<Values>) => boolean)(props)
: (isInitialValid as boolean)
}
return state.errors && Object.keys(state.errors).length === 0
},
[isInitialValid, dirty, state.errors, props, validated.current]
);

const ctx = {
Expand Down
13 changes: 13 additions & 0 deletions packages/formik/test/Formik.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,19 @@ describe('<Formik>', () => {
expect(props.submitCount).toBe(0);
});

it('should initialize isValid to false if validateOnMount until validation performed', async () => {
const validate = jest.fn(() => Promise.resolve());

const { getProps } = renderFormik({ validateOnMount: true, validate });
expect(getProps().isValid).toBe(false);

await waitFor(() => {
expect(validate).toHaveBeenCalledTimes(1);
});

expect(getProps().isValid).toBe(true);
});

describe('handleChange', () => {
it('updates values based on name attribute', () => {
const { getProps, getByTestId } = renderFormik<Values>();
Expand Down

0 comments on commit 33818d3

Please sign in to comment.