UNPKG

next-safe-action

Version:

Type safe and validated Server Actions in your Next.js project.

132 lines (128 loc) 3.44 kB
"use client"; // src/stateful-hooks.ts import * as React2 from "react"; // src/hooks-utils.ts import * as React from "react"; var getActionStatus = ({ isIdle, isExecuting, result }) => { if (isIdle) { return "idle"; } else if (isExecuting) { return "executing"; } else if ( typeof result.validationErrors !== "undefined" || typeof result.bindArgsValidationErrors !== "undefined" || typeof result.serverError !== "undefined" ) { return "hasErrored"; } else { return "hasSucceeded"; } }; var getActionShorthandStatusObject = ({ status, isTransitioning }) => { return { isIdle: status === "idle", isExecuting: status === "executing", isTransitioning, isPending: status === "executing" || isTransitioning, hasSucceeded: status === "hasSucceeded", hasErrored: status === "hasErrored", }; }; var useExecuteOnMount = (args) => { const mounted = React.useRef(false); React.useEffect(() => { const t = setTimeout(() => { if (args.executeOnMount && !mounted.current) { args.executeFn(args.executeOnMount.input); mounted.current = true; } }, args.executeOnMount?.delayMs ?? 0); return () => { clearTimeout(t); }; }, [args]); }; var useActionCallbacks = ({ result, input, status, cb }) => { const onExecuteRef = React.useRef(cb?.onExecute); const onSuccessRef = React.useRef(cb?.onSuccess); const onErrorRef = React.useRef(cb?.onError); const onSettledRef = React.useRef(cb?.onSettled); React.useEffect(() => { const onExecute = onExecuteRef.current; const onSuccess = onSuccessRef.current; const onError = onErrorRef.current; const onSettled = onSettledRef.current; const executeCallbacks = async () => { switch (status) { case "executing": await Promise.resolve(onExecute?.({ input })); break; case "hasSucceeded": await Promise.all([ Promise.resolve(onSuccess?.({ data: result?.data, input })), Promise.resolve(onSettled?.({ result, input })), ]); break; case "hasErrored": await Promise.all([ Promise.resolve(onError?.({ error: result, input })), Promise.resolve(onSettled?.({ result, input })), ]); break; } }; executeCallbacks().catch(console.error); }, [status, result, input]); }; // src/stateful-hooks.ts var useStateAction = (safeActionFn, utils) => { const [result, dispatcher, isExecuting] = React2.useActionState( safeActionFn, utils?.initResult ?? {}, utils?.permalink ); const [isIdle, setIsIdle] = React2.useState(true); const [isTransitioning, startTransition] = React2.useTransition(); const [clientInput, setClientInput] = React2.useState(); const status = getActionStatus({ isExecuting, result: result ?? {}, isIdle, }); const execute = React2.useCallback( (input) => { setTimeout(() => { setIsIdle(false); setClientInput(input); }, 0); startTransition(() => { dispatcher(input); }); }, [dispatcher] ); useExecuteOnMount({ executeOnMount: utils?.executeOnMount, executeFn: execute, }); useActionCallbacks({ result: result ?? {}, input: clientInput, status, cb: { onExecute: utils?.onExecute, onSuccess: utils?.onSuccess, onError: utils?.onError, onSettled: utils?.onSettled, }, }); return { execute, input: clientInput, result, status, ...getActionShorthandStatusObject({ status, isTransitioning }), }; }; export { useStateAction }; //# sourceMappingURL=stateful-hooks.mjs.map