Skip to content

Instantly share code, notes, and snippets.

@Eleven-am
Last active May 18, 2023 18:16
Show Gist options
  • Save Eleven-am/b76a2397ee522824d3c44ef801ff2a7a to your computer and use it in GitHub Desktop.
Save Eleven-am/b76a2397ee522824d3c44ef801ff2a7a to your computer and use it in GitHub Desktop.
This hook allows you to use the new server actions introduced in next's 13.4.
'use client';
import { useState, useRef, useMemo, useTransition, useCallback, useEffect } from 'react';
export type ServerAction = (...args: any[]) => Promise<any>;
export type Input<T extends ServerAction> = Parameters<T>;
export type Output<T extends ServerAction> = ReturnType<T> extends Promise<infer R> ? R : never;
type ServerActionType<T extends ServerAction, Value> = {
data: Value;
isPending: boolean;
mutate: (...args: Input<T>) => void;
error: Error | undefined;
}
export function useServerAction<T extends ServerAction> (action: T): ServerActionType<T, Output<T> | undefined>;
export function useServerAction<T extends ServerAction> (action: T, output: Output<T>): ServerActionType<T, Output<T>>;
export function useServerAction<T extends ServerAction> (action: T, output?: Output<T>) {
const [isPending, startTransition] = useTransition();
const [data, setData] = useState<Output<T>>(output as Output<T>);
const [error, setError] = useState<Error>();
const actionRef = useRef(action);
useEffect(() => {
setData(output as Output<T>);
setError(undefined);
}, [output]);
const mutate = useMemo(() => (...args: Input<T>) => {
startTransition(() => {
actionRef.current(...args)
.then(setData)
.catch(setError);
});
}, []);
return {
data,
isPending,
mutate,
error,
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment