I try to build a dynamic form with react-hook-form and yup by this cool guide: https://dev.to/franklin030601/dynamic-forms-with-react-hook-form-2ml8

i have this structure of data:

export const tabs: Tab[] = [
  {
    tabContent: [
      {
        label: 'Размер',
        name: 'productSize',
        placeholder: '35 px',
        sizeVariant: '15',
        type: 'text',
        validations: [
          {
            message: 'Минимум 3 символа',
            type: 'minLength',
            value: 3
          },
          {
            message: 'Обязательно к заполнению',
            type: 'required'
          }
        ],
        value: ''
      },
    ],
    tabTitle: 'Лендинг'
  },
  {
    tabContent: [
      {
        label: 'Terms and Conditions',
        name: 'terms4',
        type: 'checkbox',
        typeValue: 'boolean',
        validations: [
          {
            message: 'Accept the terms!',
            type: 'isTrue'
          }
        ],
        value: true
      },
      {
        groupTitle: 'Group 1',
        inputs: [
          {
            label: 'Terms',
            name: 'terms2',
            type: 'checkbox',
            typeValue: 'boolean',
            validations: [
              {
                message: 'Accept the terms!',
                type: 'isTrue'
              }
            ],
            value: true
          },
          {
            label: 'Checkbox 2',
            name: 'checkbox2',
            type: 'checkbox',
            typeValue: 'boolean',
            value: true
          },
          {
            label: 'Checkbox 3',
            name: 'checkbox3',
            type: 'checkbox',
            typeValue: 'boolean',
            value: false
          }
        ]
      }
    ],
    tabTitle: 'Системное'
  }
]

I process validation fields here:

type YupBoolean = Yup.BooleanSchema<boolean | undefined, Yup.AnyObject, boolean | undefined>
type YupString = Yup.StringSchema<string | undefined, Yup.AnyObject, string | undefined>
type YupNumber = Yup.NumberSchema<boolean | undefined, Yup.AnyObject, number | undefined>

/** обработчик валидаций yup */
const generateValidations = (field: InputTypes) => {
  if (!field.validations) return null

  /** задает схему */
  let schema: YupBoolean | YupString = Yup[field.typeValue || 'string']()

  for (
    /** пробегается по правилам из данных validations */
    const rule of field.validations) {
    switch (rule.type) {
      case 'isTrue' : schema = (schema as YupBoolean).isTrue(rule.message); break
      case 'isEmail' : schema = (schema as YupString).email(rule.message); break
      case 'minLength': schema = (schema as YupString).min(rule?.value as number, rule.message); break
      case 'oneOf' : schema = (schema as YupString).oneOf([Yup.ref((rule as any).ref)], rule.message); break
      default : schema = schema.required(rule.message); break
    }
  }

  return schema
}

I then try to spread form into tabs with react-tabs:

/** страница тестовая */
const TestPage = () => {
  /** дата */
  const anotherForm = transformForm(tabs)

  console.log('anotherForm.validationsFields', anotherForm.validationsFields)

  /** методы из формы */
  const formMethods = useForm({
    defaultValues: { ...(anotherForm.initialValues as any) },
    mode: 'onSubmit',
    resolver: yupResolver(anotherForm.validationsFields)
  })

  /** обработчик сабмита */
  const onSubmit = (data) => {
    console.log('data', data)
  }

  return (
    <section>
      <FormProvider {...formMethods}>
        <form
          className=''
          onSubmit={formMethods.handleSubmit(onSubmit)}
        >
          <Tabs>
            <TabList>
              {anotherForm.tabs.map((tab, index) => (
                <Tab key={index}>
                  {tab.tabTitle}
                </Tab>
              ))}
            </TabList>

            {anotherForm.tabs.map((tab, index) => (
              <TabPanel key={index}>
                <>
                  <h2>
                    {tab.tabTitle}
                  </h2>
                  <Form tabContent={tab.tabContent} />
                </>
              </TabPanel>
            ))}
          </Tabs>
          <button type='submit'>
            submit
          </button>
          <TabsUnderline />
        </form>
      </FormProvider>
    </section>

validation schema looks like this: schema after processing

Everything works fine if i dont try to put fields in tabs and make 1 long page with all fields, or if i turn off resolver. But if i try to switch between tabs, i get error

**TypeError: o[(intermediate value)(intermediate value)(intermediate value)] is not a function**

As i understand, this is something to be with context in useForm, or schemas context. I could not manage to solve it.

Another question: i need to save entered data locally by switching the tabs, get backend data by reloading the page and send entered data to the server only by clicking submit button. I dont want to use any state manager. Do i use react-hook-form in the right way here?

0

There are 0 answers