Skip to content

Commit affb616

Browse files
committed
fix(formik): validateOnMount initialize isValid to false until validation performed
1 parent c798145 commit affb616

File tree

2 files changed

+27
-9
lines changed

2 files changed

+27
-9
lines changed

packages/formik/src/Formik.tsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ export function useFormik<Values extends FormikValues = FormikValues>({
152152
const initialTouched = React.useRef(props.initialTouched || emptyTouched);
153153
const initialStatus = React.useRef(props.initialStatus);
154154
const isMounted = React.useRef<boolean>(false);
155+
const validated = React.useRef<boolean>(false);
155156
const fieldRegistry = React.useRef<FieldRegistry>({});
156157
if (__DEV__) {
157158
// eslint-disable-next-line react-hooks/rules-of-hooks
@@ -314,6 +315,7 @@ export function useFormik<Values extends FormikValues = FormikValues>({
314315
props.validationSchema ? runValidationSchema(values) : {},
315316
props.validate ? runValidateHandler(values) : {},
316317
]).then(([fieldErrors, schemaErrors, validateErrors]) => {
318+
validated.current = true;
317319
const combinedErrors = deepmerge.all<FormikErrors<Values>>(
318320
[fieldErrors, schemaErrors, validateErrors],
319321
{ arrayMerge }
@@ -949,15 +951,18 @@ export function useFormik<Values extends FormikValues = FormikValues>({
949951
);
950952

951953
const isValid = React.useMemo(
952-
() =>
953-
typeof isInitialValid !== 'undefined'
954-
? dirty
955-
? state.errors && Object.keys(state.errors).length === 0
956-
: isInitialValid !== false && isFunction(isInitialValid)
957-
? (isInitialValid as (props: FormikConfig<Values>) => boolean)(props)
958-
: (isInitialValid as boolean)
959-
: state.errors && Object.keys(state.errors).length === 0,
960-
[isInitialValid, dirty, state.errors, props]
954+
() => {
955+
if (!validated.current && validateOnMount) return false
956+
if (typeof isInitialValid !== 'undefined') {
957+
if (dirty) return state.errors && Object.keys(state.errors).length === 0;
958+
959+
return isInitialValid !== false && isFunction(isInitialValid)
960+
? (isInitialValid as (props: FormikConfig<Values>) => boolean)(props)
961+
: (isInitialValid as boolean)
962+
}
963+
return state.errors && Object.keys(state.errors).length === 0
964+
},
965+
[isInitialValid, dirty, state.errors, props, validated.current]
961966
);
962967

963968
const ctx = {

packages/formik/test/Formik.test.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,19 @@ describe('<Formik>', () => {
128128
expect(props.submitCount).toBe(0);
129129
});
130130

131+
it('should initialize isValid to false if validateOnMount until validation performed', async () => {
132+
const validate = jest.fn(() => Promise.resolve());
133+
134+
const { getProps } = renderFormik({ validateOnMount: true, validate });
135+
expect(getProps().isValid).toBe(false);
136+
137+
await waitFor(() => {
138+
expect(validate).toHaveBeenCalledTimes(1);
139+
});
140+
141+
expect(getProps().isValid).toBe(true);
142+
});
143+
131144
describe('handleChange', () => {
132145
it('updates values based on name attribute', () => {
133146
const { getProps, getByTestId } = renderFormik<Values>();

0 commit comments

Comments
 (0)