Поля ввода теряют фокус при каждом изменении значения в сложной форме Formik - PullRequest
2 голосов
/ 29 февраля 2020

Я создаю приложение, которое будет нуждаться в генерации сложной формы (из объекта json / js).

Вот пример того, что я строю: https://codesandbox.io/s/formik-form-wizard-test-vcj1t

Моя проблема заключается в следующем:

все поля ввода теряют фокус при каждом изменении значения


Структура папок CodeSandbox Проект выглядит следующим образом (для облегчения понимания кода):

./src:

  • App.js - основной файл со всеми генерациями форм (generateWizardSteps - это основная функция, которая выполняет все генерации).

  • formSetup.js - это объект, который определяет конфигурацию формы. Из таких объектов мне нужно построить динамические c формы. Этот объект имеет массив pages (это шаги мастера), а каждый page имеет массив fields (например, input, select, checkbox et c). В свою очередь, каждый field имеет свойство props. props - это то, что я передаю компоненту React в качестве реквизита.

  • formComponents.js - этот файл содержит все поля формы компонентов React, которые я использую для генерации своих форм.

  • decorateWithFormik.js - этот файл просто делает App.js немного меньше. Это просто декоратор useFormik.


Форма построена с использованием библиотеки formik . Кроме того, поскольку мне нужна форма, подобная мастеру, я нашел для нее хорошую библиотеку: formik-wizard-form .

Я просмотрел вопросы стека переполнения на аналогичные темы но не мог найти то, что могло бы соответствовать моим потребностям. Многие вопросы / ответы касаются проблемы с динамическими c key реквизитами, но мои, насколько я могу судить, stati c (все они взяты из исходного объекта formSetup).

Еще одна вещь, которую я заметил, это то, что моя форма перерисовывается при каждом изменении значения, но я не уверен, что это вообще проблема.


Не могли бы вы помочь мне понять в чем проблема, почему это происходит и как заставить мои поля формы не терять фокус?

1 Ответ

1 голос
/ 03 марта 2020

Решена проблема

Я удалил весь возможный код создания компонента и переместил все в подпорки component компонента Step, предоставленного библиотекой formik-wizard-form .

Вот мое рабочее решение: https://codesandbox.io/s/formik-form-wizard-test-lz3x7 (надеюсь, это кому-нибудь поможет)

Большое спасибо всем в разделе комментариев!


Основные идеи:

  1. Потеря фокуса означает, что компонент unmounts and remounts каждый раз.

  2. Это отключение / Поведение перемонтирования при каждом изменении было вызвано созданием компонентов внутри функции render другого компонента. Следовательно, при каждом повторном рендеринге компоненты ввода создавались заново.


Мой окончательный рабочий код:

const MyForm = props => {
  return (
    <FormikWizardProvider {...props}>
      {renderProps => (
        <Wizard {...renderProps}>
          <StepsList>
            {formSetup.pages.map(page => (
              <Step
                title={page.name}
                key={page.name}
                component={() =>
                  page.fields.map(field => {
                    if (
                      field.props &&
                      field.props.visibilityCheckbox &&
                      !props.values[field.props.visibilityCheckbox]
                    ) {
                      return null;
                    }

                    const fieldProps = {
                      formik: props,
                      key: field.props.name,
                      ...field.props
                    };

                    switch (field.type) {
                      case "input":
                        return <MyTextInput {...fieldProps} />;
                      case "radio":
                        return <RadioButtonGroup {...fieldProps} />;
                      case "checkbox":
                        return <MyCheckbox {...fieldProps} />;
                      case "select":
                        return <MySelect {...fieldProps} />;

                      default:
                        return null;
                    }
                  })
                }
              />
            ))}
          </StepsList>
          <ButtonsList>
            <PreviousButton />
            <NextButton />
            <SubmitButton />
          </ButtonsList>
        </Wizard>
      )}
    </FormikWizardProvider>
  );
};

export default decorateWizardWithFormik(MyForm);
...