UNPKG

remix-validated-form

Version:

Form component and utils for easy form validation in remix

75 lines (74 loc) 3.11 kB
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime"; import { useMemo } from "react"; import { useCallback } from "react"; import invariant from "tiny-invariant"; import { useFieldDefaultValue, useFieldError, useInternalFormContext, useInternalHasBeenSubmitted, useValidateField, } from "../hooks"; import { useRegisterControlledField } from "./controlledFields"; import { useFormStore } from "./storeHooks"; const useInternalFieldArray = (context, field, validationBehavior) => { const value = useFieldDefaultValue(field, context); useRegisterControlledField(context, field); const hasBeenSubmitted = useInternalHasBeenSubmitted(context.formId); const validateField = useValidateField(context.formId); const error = useFieldError(field, context); const resolvedValidationBehavior = { initial: "onSubmit", whenSubmitted: "onChange", ...validationBehavior, }; const behavior = hasBeenSubmitted ? resolvedValidationBehavior.whenSubmitted : resolvedValidationBehavior.initial; const maybeValidate = useCallback(() => { if (behavior === "onChange") { validateField(field); } }, [behavior, field, validateField]); invariant(value === undefined || value === null || Array.isArray(value), `FieldArray: defaultValue value for ${field} must be an array, null, or undefined`); const arr = useFormStore(context.formId, (state) => state.controlledFields.array); const helpers = useMemo(() => ({ push: (item) => { arr.push(field, item); maybeValidate(); }, swap: (indexA, indexB) => { arr.swap(field, indexA, indexB); maybeValidate(); }, move: (from, to) => { arr.move(field, from, to); maybeValidate(); }, insert: (index, value) => { arr.insert(field, index, value); maybeValidate(); }, unshift: (value) => { arr.unshift(field, value); maybeValidate(); }, remove: (index) => { arr.remove(field, index); maybeValidate(); }, pop: () => { arr.pop(field); maybeValidate(); }, replace: (index, value) => { arr.replace(field, index, value); maybeValidate(); }, }), [arr, field, maybeValidate]); const arrayValue = useMemo(() => value !== null && value !== void 0 ? value : [], [value]); return [arrayValue, helpers, error]; }; export function useFieldArray(name, { formId, validationBehavior } = {}) { const context = useInternalFormContext(formId, "FieldArray"); return useInternalFieldArray(context, name, validationBehavior); } export const FieldArray = ({ name, children, formId, validationBehavior, }) => { const context = useInternalFormContext(formId, "FieldArray"); const [value, helpers, error] = useInternalFieldArray(context, name, validationBehavior); return _jsx(_Fragment, { children: children(value, helpers, error) }); };