Best Practices for Combining Server and Client Components with CRUD Operations
Answered
Siberian posted this in #help-forum
SiberianOP
I'm trying to achieve a setup where I use a getAll function in a server component to fetch all the data. This data is then passed to a table, which is a client component. Inside the client component, I have modals for adding, editing, and deleting records, with the actual add, edit, and delete functionalities being handled within the client component. These actions make asynchronous requests to the server.
I'm planning to use React Query to manage state for my client components. Since every request in the client components is performed asynchronously, I want to ensure that when I refresh the page, the server component still loads quickly with the data.
Could someone guide me on the best approach to structure this? Also, if you have any suggestions or best practices for handling such a setup in Next.js, I'd really appreciate it.
I'm planning to use React Query to manage state for my client components. Since every request in the client components is performed asynchronously, I want to ensure that when I refresh the page, the server component still loads quickly with the data.
Could someone guide me on the best approach to structure this? Also, if you have any suggestions or best practices for handling such a setup in Next.js, I'd really appreciate it.
Answered by P𝑠eudo
I don't know if this is the best approach, but the way I would do it is I use server actions for the modals since its just simple mutations. You don't have to do React Query to perform this, you simply just call the function that has
More info here: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
For the forms: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#forms
use server
directive.More info here: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
For the forms: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#forms
8 Replies
I don't know if this is the best approach, but the way I would do it is I use server actions for the modals since its just simple mutations. You don't have to do React Query to perform this, you simply just call the function that has
More info here: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
For the forms: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#forms
use server
directive.More info here: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
For the forms: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#forms
Answer
@P𝑠eudo I don't know if this is the best approach, but the way I would do it is I use server actions for the modals since its just simple mutations. You don't have to do React Query to perform this, you simply just call the function that has `use server` directive.
More info here: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
For the forms: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#forms
SiberianOP
Thank you for your response. I will look into this. I used react query since I am familiar with it from React.
@Siberian Thank you for your response. I will look into this. I used react query since I am familiar with it from React.
This is fine, if you're going to use a different framework (like express or hono) as your backend, or you require different HTTP request methods. Calling the server actions is basically just a
fetch
with POST as the request method. (Try experimenting with server actions and check the Network tab in the browsers dev tools)@P𝑠eudo I don't know if this is the best approach, but the way I would do it is I use server actions for the modals since its just simple mutations. You don't have to do React Query to perform this, you simply just call the function that has `use server` directive.
More info here: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
For the forms: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#forms
SiberianOP
I would like to update that this works wonderfully. thank you very much.
I used eventActions:
export async function addEvent(data: Partial<Event>) {
const result = await FirestoreController.createOne('events', data);
return result;
}
export async function editEvent(data: Partial<Event> & { _id: string }) {
const { _id, ...updateData } = data;
await FirestoreController.updateOne('events', _id, updateData);
return data;
}
export async function deleteEvent(_id: string) {
await FirestoreController.deleteOne('events', _id);
return _id;
}
and I just call them to my modal dialog:
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
const result = await addEvent(formState);
if (result) {
onAdd(result as Event);
onClose();
}
};
@Siberian I used eventActions:
`export async function addEvent(data: Partial<Event>) {
const result = await FirestoreController.createOne('events', data);
return result;
}
export async function editEvent(data: Partial<Event> & { _id: string }) {
const { _id, ...updateData } = data;
await FirestoreController.updateOne('events', _id, updateData);
return data;
}
export async function deleteEvent(_id: string) {
await FirestoreController.deleteOne('events', _id);
return _id;
}
`
Before I forget, server actions are basically API endpoints behind the scenes (like I said, its just a
You can watch this short clips (its worth to watch):
https://www.youtube.com/watch?v=wh4kGL1EIGM
https://www.youtube.com/watch?v=VKSAWNb3h4I (if you're familiar with server actions, you can skip to 9:30)
fetch
with POST), its just that it simply enhances DX for me. So don't forget to do authentication/authorization checks on your server actions, something like this:'use server';
import { getSession } from '@/lib/auth';
export async function deleteUser(userId: string){
const { session } = await getSession();
if (!session?.user) throw Error ("Unauthorized");
if (session?.user.role !== admin) throw Error("Requires admin privileges");
...
}
You can watch this short clips (its worth to watch):
https://www.youtube.com/watch?v=wh4kGL1EIGM
https://www.youtube.com/watch?v=VKSAWNb3h4I (if you're familiar with server actions, you can skip to 9:30)
@P𝑠eudo Before I forget, server actions are basically API endpoints behind the scenes (like I said, its just a `fetch` with POST), its just that it simply enhances DX for me. So don't forget to do authentication/authorization checks on your server actions, something like this:
'use server';
import { getSession } from '@/lib/auth';
export async function deleteUser(userId: string){
const { session } = await getSession();
if (!session?.user) throw Error ("Unauthorized");
if (session?.user.role !== admin) throw Error("Requires admin privileges");
...
}
You can watch this short clips (its worth to watch):
https://www.youtube.com/watch?v=wh4kGL1EIGM
https://www.youtube.com/watch?v=VKSAWNb3h4I (if you're familiar with server actions, you can skip to 9:30)
SiberianOP
thank you. I will keep this in mind. I think f irebase has strong built in authentication but I can also add an extra layer on top of it.