Skip to content

Instantly share code, notes, and snippets.

@floatrx
Created June 28, 2024 14:35
Show Gist options
  • Save floatrx/f541d9a154e2da40b8f00e5fda772fdd to your computer and use it in GitHub Desktop.
Save floatrx/f541d9a154e2da40b8f00e5fda772fdd to your computer and use it in GitHub Desktop.
useServerAction with examples #hook #nextjs
'use server';
import type { TNote } from '@/types/note';
import { revalidatePath } from 'next/cache';
import { noteService } from '@/features/note/services/note';
export async function deleteNote(id: TNote['id']) {
const { error } = await noteService.remove(id);
if (error) return;
revalidatePath('/notes');
}
'use client';
import type { TNote } from '@/types/note';
import { Button } from '@nextui-org/button';
import { Trash2 } from 'lucide-react';
import { deleteNote } from '@/features/note/actions/deleteNote';
import { useServerAction } from '@/hooks/useServerAction';
export const DeleteNoteButton = (props: Pick<TNote, 'id'>) => {
const { loading, execute } = useServerAction(deleteNote);
return (
<Button isIconOnly isLoading={loading} size="sm" variant="ghost" onClick={() => execute(props.id)}>
<Trash2 size={15} />
</Button>
);
};
import { useState } from 'react';
type AsyncFn = (...args: any) => Promise<any>;
/**
* Use this hook to execute server actions in the client side
* It will handle loading, error and data states...
* @param action
* @example
* export const DeleteButton = ({id}) => {
* const { loading, execute } = useServerAction(deleteNote);
* return (
* <Button isLoading={loading} onClick={() => execute(id)}>Delete</Button>
* );
* };
*/
export const useServerAction = <T extends AsyncFn>(action: T) => {
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
const [data, setData] = useState<Awaited<ReturnType<T>> | null>(null);
const execute = async (...args: Parameters<T>) => {
setLoading(true);
setError(null);
setData(null);
try {
const res = await action(...args);
setData(res);
return res as Awaited<ReturnType<T>>;
} catch (e) {
console.log('Error:', e.message);
setError(e);
} finally {
setLoading(false);
}
};
return {
data,
loading,
error,
execute,
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment