Объединение нескольких форм в один мастер форм, используя монадический подход
react-form-mozard
React-form-mozard помогает вам легко создавать многошаговые формы (также известные как мастера форм).
Установка
npm i react-form-mozard
Мотивация
Многошаговая форма — распространенный шаблон в веб-разработке. Однако он вводит сложное и грязное управление состоянием. Решением снова является монада.
Моцард сочиняет формы так же, как Моцарт сочиняет песни.
Пример
const { elements, done, value, get } = useMozard<MozardSchema, Result>({
values,
onNext: setValue,
*do(step) {
const { name, age } = yield* step("profile", ProfileForm, {});
const isMinor = age < 20;
const { country } = yield* step("country", CountryForm, { isMinor });
if (country !== "Korea") {
return { name, age, country };
}
const { side } = yield* step("whichKorea", WhichKoreaForm, {});
return { name, age, country: `${side} ${country}` }
};
},
});
Давайте разберем приведенный выше код.
const { name, age } = yield* step("profile", ProfileForm, {});
Вы можете понимать эту строку как:
const { name, age } = yield* <ProfileForm key="profile">
Это означает, что ProfileForm
отображается для получения имени и возраста. Текущий интерфейс представлен для вывода типов, хотя версия JSX
более лаконична.
Предполагается, что ProfileForm
имеет реквизит с именем onSubmit
, который представляет собой функцию, которая принимает name
и age
в качестве аргументов.
function ProfileForm(props: { onSubmit(value: { name: string, age: number }): void }) {
// ...
}
Значение, передаваемое в onSubmit
, будет значением yield* step"profile", ProfileForm, {})
. Вы можете использовать их, чтобы установить реквизиты для следующего компонента формы, или использовать их, чтобы решить, к какому шагу перейти дальше.
elements
— это массив элементов, которые были отрисованы на данный момент. Вы можете визуализировать их все одновременно, например:
return (
<SomeLayout>
{elements}
</SomeLayout>
);
Kоторый отображает все подчиненные формы, которые отправили свои значения, а также текущий шаг.
Или вы можете визуализировать только последний элемент, например:
return (
<SomeLayout>
{!done && elements.at(-1)}
</SomeLayout>
);
Последний элемент — это текущий шаг, который еще не отправил свое значение. Done
указывает, заполнена ли вся форма.
Более подробный пример доступен здесь.