@next-safe-action/adapter-react-hook-form
Version:
This adapter offers a way to seamlessly integrate next-safe-action with react-hook-form.
97 lines (93 loc) • 2.62 kB
JavaScript
"use client";
// src/hooks.ts
import { useAction, useOptimisticAction } from "next-safe-action/hooks";
import * as React from "react";
import { useForm } from "react-hook-form";
// src/index.ts
function mapToHookFormErrors(validationErrors, props) {
if (!validationErrors || Object.keys(validationErrors).length === 0) {
return void 0;
}
const fieldErrors = {};
function mapper(ve, paths = []) {
for (const key of Object.keys(ve)) {
if (typeof ve[key] === "object" && ve[key] && !Array.isArray(ve[key])) {
mapper(ve[key], [...paths, key]);
}
if (key === "_errors" && Array.isArray(ve[key])) {
let ref = fieldErrors;
for (let i = 0; i < paths.length - 1; i++) {
const p = paths[i];
ref[p] ??= {};
ref = ref[p];
}
const path = paths.at(-1) ?? "root";
ref[path] = {
type: "validate",
message: ve[key].join(props?.joinBy ?? " "),
};
}
}
}
mapper(validationErrors ?? {});
return fieldErrors;
}
// src/hooks.ts
function useHookFormActionErrorMapper(validationErrors, props) {
const propsRef = React.useRef(props);
const hookFormValidationErrors = React.useMemo(
() => mapToHookFormErrors(validationErrors, propsRef.current),
[validationErrors]
);
return {
hookFormValidationErrors,
};
}
function useHookFormAction(safeAction, hookFormResolver, props) {
const action = useAction(safeAction, props?.actionProps);
const { hookFormValidationErrors } = useHookFormActionErrorMapper(
action.result.validationErrors,
props?.errorMapProps
);
const form = useForm({
...props?.formProps,
resolver: hookFormResolver,
errors: hookFormValidationErrors,
});
const handleSubmitWithAction = form.handleSubmit(action.executeAsync);
const resetFormAndAction = () => {
form.reset();
action.reset();
};
return {
action,
form,
handleSubmitWithAction,
resetFormAndAction,
};
}
function useHookFormOptimisticAction(safeAction, hookFormResolver, props) {
const action = useOptimisticAction(safeAction, props.actionProps);
const { hookFormValidationErrors } = useHookFormActionErrorMapper(
action.result.validationErrors,
props.errorMapProps
);
const form = useForm({
...props?.formProps,
resolver: hookFormResolver,
errors: hookFormValidationErrors,
});
const handleSubmitWithAction = form.handleSubmit(action.executeAsync);
const resetFormAndAction = () => {
form.reset();
action.reset();
};
return {
action,
form,
handleSubmitWithAction,
resetFormAndAction,
};
}
export { useHookFormAction, useHookFormActionErrorMapper, useHookFormOptimisticAction };
//# sourceMappingURL=hooks.mjs.map