formik-antd icon indicating copy to clipboard operation
formik-antd copied to clipboard

Run a function over errors in Form.Item / validationSchema? (Yup, i18next)

Open yoruvo opened this issue 4 years ago • 2 comments

Hi,

my setup for forms is:

  • formik and formik-antd for the form creation
  • Yup for validation
  • react-i18next for localization

This setup works quite well for labels, placeholders etc. but I'm struggling with errors.

If I design my validation schema for Formik like so:

import * as Yup from "yup"
import { useTranslation } from "react-i18next"

const { t } = useTranslation()

  const validationSchema = Yup.object().shape({
    name: Yup.string().required(t("form.validation.required")),
  })

then the validation is translated correctly, but the translation does not change when switching languages in i18next.

A solution suggested in many other issues I've read about the topic (from the different projects) is to use the i18next t() function in the React output instead. However, for me, this is being handled by formik-antd's Form.Item class.

However, I cannot see any option to pass that t() function to the Form.Item error output without overriding the Form.Item.

Could you advise on how to proceed?

yoruvo avatar May 27 '20 08:05 yoruvo

You might be able to place the schema and the calls to the t function inside a component. To not reintantiate the schema on every render you probabaly want to wrap it in a React.useMemo call. The memo need to be re-evaluated on every language change. I guess the react-i18next exposes somewhere the current language value in a hook. This value you would need to pass to the memo as a dependency.

So something along these lines:

function MyComponent() {
  const { t, lang } = useTranslation(); // not sure how to get lang, it might be somewhere else
  const schema = React.useMemo(()=> {
     return /* Yup.object().shape.... with t() calls*/, 
       , [lang]); // <-- dependency for useMemo, so that on every change of `lang` the schema gets re-created
  return <Formik ....
}

jannikbuschke avatar May 27 '20 15:05 jannikbuschke

I agree this would be useful and the solution suggested isn't possible in my case because my validation schema does not return translated messages but rather a serialized object to generate the translated message. I do this because my API needs to be language agnostic, and some form errors are generated there.

I was solving this before using Antd with a custom ErrorMessage component, but with Antd, the error is internal to the FormItem.

ryall avatar Jun 29 '20 11:06 ryall