Next.js Discord

Discord Forum

Tanstack query syntax with server action

Unanswered
American posted this in #help-forum
Open in Discord
AmericanOP
💬 Hey everyone!
I’m working with TanStack Query + Next.js and wanted some advice or suggestions.

Here’s the flow I’m using:
1️⃣ Server action (createContentSubmission):
'use server';
const createContentSubmissionSchema = z.object({
  contentId: z.string().uuid(),
});

export async function createContentSubmission(formData: FormData) {
  const contentId = formData.get('contentId');
  const parsed = createContentSubmissionSchema.safeParse({ contentId });

  if (!parsed.success) {
    throw new Error('Invalid input');
  }

  const userId = await getUserId();

  try {
    await prisma.submission.create({
      data: {
        contentId: parsed.data.contentId,
        status: 'IN_PROGRESS',
        userId: userId,
      },
    });

    return { success: true };
  } catch (e) {
    throw new Error('Failed to create submission');
  }
}

2️⃣ Client-side call using useMutation:
const { mutate, isPending } = useMutation({
  mutationFn: async (contentId: string) => {
    const formData = new FormData();
    formData.append('contentId', contentId);
    await createContentSubmission(formData);
  },
  onSuccess: () => {
    router.push(`${pathname}/content`);
  },
  onError: (error) => {
    toast.error(error instanceof Error ? error.message : 'Failed to create submission');
  },
});

And the button triggers it like:
<Button onClick={() => mutate(contentId)} disabled={isPending}>
  I understand, start now
</Button>

🔧 My questions:
✅ Is this the best or most Next.js-friendly way to call a server action from a client component?
✅ Are there better practices for error handling or optimistic updates here?

Would love to hear how others are doing this! 🙏

0 Replies