From ccdcb3979a0ca7de99e017a544fcaee3ef7e5936 Mon Sep 17 00:00:00 2001 From: john-raymon Date: Tue, 1 Aug 2023 01:33:00 -0400 Subject: [PATCH 1/2] pass Yup context to validationSchema using new prop validationSchemaContext --- packages/formik/src/Formik.tsx | 6 ++++-- packages/formik/src/types.tsx | 6 ++++++ packages/formik/test/Formik.test.tsx | 24 ++++++++++++++++++++++++ packages/formik/test/yupHelpers.test.ts | 18 ++++++++++++++++++ 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/packages/formik/src/Formik.tsx b/packages/formik/src/Formik.tsx index db627821d..16eadbb47 100755 --- a/packages/formik/src/Formik.tsx +++ b/packages/formik/src/Formik.tsx @@ -235,8 +235,10 @@ export function useFormik({ : validationSchema; const promise = field && schema.validateAt - ? schema.validateAt(field, values) - : validateYupSchema(values, schema); + ? schema.validateAt(field, values, { + context: props.validationSchemaContext + }) + : validateYupSchema(values, schema, false, props.validationSchemaContext); return new Promise((resolve, reject) => { promise.then( () => { diff --git a/packages/formik/src/types.tsx b/packages/formik/src/types.tsx index 9586fe865..17b6ab4c4 100644 --- a/packages/formik/src/types.tsx +++ b/packages/formik/src/types.tsx @@ -223,6 +223,12 @@ export interface FormikConfig extends FormikSharedConfig { values: Values, formikHelpers: FormikHelpers ) => void | Promise; + + /** + * A context object to be passed to the Yup schema's `validate` method. + */ + validationSchemaContext?: any; + /** * A Yup Schema or a function that returns a Yup schema */ diff --git a/packages/formik/test/Formik.test.tsx b/packages/formik/test/Formik.test.tsx index 2acf332dd..3aaf43e82 100644 --- a/packages/formik/test/Formik.test.tsx +++ b/packages/formik/test/Formik.test.tsx @@ -1454,4 +1454,28 @@ describe('', () => { expect(innerRef.current).toEqual(getProps()); }); + + it('should pass context to validationSchema', async () => { + const validationSchema = Yup.object().shape({ + usernameOrEmail: Yup.string().when( + '$validateAsEmail', + (validateAsEmail, schema) => + validateAsEmail ? schema.email('Invalid email') : schema + ), + }); + + const { getProps } = renderFormik({ + initialValues: { usernameOrEmail: 'john' }, + validationSchema, + validationSchemaContext: { validateAsEmail: true }, + }); + + await act(async () => { + await getProps().validateForm(); + }); + + expect(getProps().errors).toEqual({ + usernameOrEmail: 'Invalid email', + }); + }); }); diff --git a/packages/formik/test/yupHelpers.test.ts b/packages/formik/test/yupHelpers.test.ts index 15261e186..0df380390 100644 --- a/packages/formik/test/yupHelpers.test.ts +++ b/packages/formik/test/yupHelpers.test.ts @@ -22,6 +22,12 @@ const deepNestedSchema = Yup.object({ }), }); +const whenContextSchema = Yup.object().shape({ + name: Yup.string().when('$isNameRequired', (isNameRequired, schema) => { + return isNameRequired ? schema.required('name is required') : schema; + }), +}); + describe('Yup helpers', () => { describe('yupToFormErrors()', () => { it('should transform Yup ValidationErrors into an object', async () => { @@ -109,5 +115,17 @@ describe('Yup helpers', () => { ]); } }); + + it('should provide context values as context to when method', async () => { + try { + await validateYupSchema({ name: '' }, whenContextSchema, false, { + isNameRequired: true, + }); + } catch (e) { + const err = e as Yup.ValidationError; + expect(err.name).toEqual('ValidationError'); + expect(err.errors).toEqual(['name is required']); + } + }); }); }); From 2ef7ef601736c9ab12ce475462ddcde2abd8ddaf Mon Sep 17 00:00:00 2001 From: john-raymon Date: Tue, 1 Aug 2023 01:57:54 -0400 Subject: [PATCH 2/2] add validationSchemaContext to formik api docs --- docs/api/formik.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/api/formik.md b/docs/api/formik.md index 0dfec7603..307e58b17 100644 --- a/docs/api/formik.md +++ b/docs/api/formik.md @@ -458,3 +458,7 @@ and/or `initialValues` change. [A Yup schema](https://github.com/jquense/yup) or a function that returns a Yup schema. This is used for validation. Errors are mapped by key to the inner component's `errors`. Its keys should match those of `values`. + +### `validationSchemaContext?: object` + +A [context object](https://github.com/jquense/yup#schemavalidatevalue-any-options-object-promiseinfertypeschema-validationerror) that is passed to the [Yup schema](https://github.com/jquense/yup) provided via the [validationSchema prop](#validationschema-schema----schema).