remix-validated-form
Version:
Form component and utils for easy form validation in remix
85 lines (84 loc) • 3.45 kB
JavaScript
import { useEffect, useMemo } from "react";
import { createGetInputProps, } from "./internal/getInputProps";
import { useInternalFormContext, useFieldTouched, useFieldError, useFieldDefaultValue, useClearError, useInternalIsSubmitting, useInternalIsValid, useInternalHasBeenSubmitted, useValidateField, useRegisterReceiveFocus, } from "./internal/hooks";
import { useControllableValue, useUpdateControllableValue, } from "./internal/state/controlledFields";
/**
* Returns whether or not the parent form is currently being submitted.
* This is different from remix's `useTransition().submission` in that it
* is aware of what form it's in and when _that_ form is being submitted.
*
* @param formId
*/
export const useIsSubmitting = (formId) => {
const formContext = useInternalFormContext(formId, "useIsSubmitting");
return useInternalIsSubmitting(formContext.formId);
};
/**
* Returns whether or not the current form is valid.
*
* @param formId the id of the form. Only necessary if being used outside a ValidatedForm.
*/
export const useIsValid = (formId) => {
const formContext = useInternalFormContext(formId, "useIsValid");
return useInternalIsValid(formContext.formId);
};
/**
* Provides the data and helpers necessary to set up a field.
*/
export const useField = (name, options) => {
const { formId: providedFormId, handleReceiveFocus } = options !== null && options !== void 0 ? options : {};
const formContext = useInternalFormContext(providedFormId, "useField");
const defaultValue = useFieldDefaultValue(name, formContext);
const [touched, setTouched] = useFieldTouched(name, formContext);
const error = useFieldError(name, formContext);
const clearError = useClearError(formContext);
const hasBeenSubmitted = useInternalHasBeenSubmitted(formContext.formId);
const validateField = useValidateField(formContext.formId);
const registerReceiveFocus = useRegisterReceiveFocus(formContext.formId);
useEffect(() => {
if (handleReceiveFocus)
return registerReceiveFocus(name, handleReceiveFocus);
}, [handleReceiveFocus, name, registerReceiveFocus]);
const field = useMemo(() => {
const helpers = {
error,
clearError: () => clearError(name),
validate: () => {
validateField(name);
},
defaultValue,
touched,
setTouched,
};
const getInputProps = createGetInputProps({
...helpers,
name,
hasBeenSubmitted,
validationBehavior: options === null || options === void 0 ? void 0 : options.validationBehavior,
});
return {
...helpers,
getInputProps,
};
}, [
error,
clearError,
defaultValue,
touched,
setTouched,
name,
hasBeenSubmitted,
options === null || options === void 0 ? void 0 : options.validationBehavior,
validateField,
]);
return field;
};
export const useControlField = (name, formId) => {
const context = useInternalFormContext(formId, "useControlField");
const [value, setValue] = useControllableValue(context, name);
return [value, setValue];
};
export const useUpdateControlledField = (formId) => {
const context = useInternalFormContext(formId, "useControlField");
return useUpdateControllableValue(context.formId);
};