Next.js Discord

Discord Forum

How to I trigger data refresh on a parent RSC when a child triggers a server action?

Answered
WebDevSayantan posted this in #help-forum
Open in Discord
I have an Invoices component(RSC) which shows a list of InvoiceCard components(RSC). The InvoiceCard component contains a DeleteButton(React Client Component) that invokes a server action to delete an invoice. How to I refresh the list of invoices, fetched in the top level Invoices Component when I call this delete server action?

Invoices & InvoiceCard component:
export default async function Invoices({
  params,
}: { params: { homestay: string } }) {
  // how do I update this list when delete server action is triggered from it's child component? 
  const invoices = await getAllInvoices(params.homestay);
  return (
    <div>
      {invoices.map((invoice) => (
        <InvoiceCard key={invoice.id} invoice={invoice} />
      ))}
    </div>
  );
}

export default async function InvoiceCard({
  invoice,
}: { invoice: InvoiceCardProps }) {
  return (
    <Card>
      {/* Divs showing invoice data  */}
      <CardFooter>
          {invoice.id && (
            <DeleteButton
              invoiceId={invoice.id}
              deleteInvoice={deleteInvoiceAction}
            />
          )}
      </CardFooter>
    </Card>
  );
}

DeleteInvoice Server Action
"use server";
// imports and stuff
export async function deleteInvoiceAction(invoiceId: number) {
  const deleted = await deleteInvoice(invoiceId); // db call to delete invoice
  return deleted.length > 0 ? deleted[0].id : null;
}


DeleteButton Client Component
// the server action is passed as prop from invoiceCard component
export default function DeleteButton({
  invoiceId,
  deleteInvoice,
}: any) {
  const [open, setOpen] = useState(false);
  return (
    {* 'Server action which was send via prop is triggered' *}
    <Button variant="destructive"
      onClick={async () => {
        await deleteInvoice(invoiceId);
        setOpen(false);
      }}
    > Delete
    </Button>
  );
}
Answered by Ray
use revalidatePath in server action
"use server";
// imports and stuff
export async function deleteInvoiceAction(invoiceId: number) {
  const deleted = await deleteInvoice(invoiceId); // db call to delete invoice

  if (deleted.length) {
    revalidatePath("/invoices")
  }
  return deleted.length > 0 ? deleted[0].id : null;
}
View full answer

2 Replies

@WebDevSayantan I have an Invoices component(RSC) which shows a list of InvoiceCard components(RSC). The InvoiceCard component contains a DeleteButton(React Client Component) that invokes a server action to delete an invoice. How to I refresh the list of invoices, fetched in the top level Invoices Component when I call this delete server action? **Invoices & InvoiceCard component:** typescript export default async function Invoices({ params, }: { params: { homestay: string } }) { // how do I update this list when delete server action is triggered from it's child component? const invoices = await getAllInvoices(params.homestay); return ( <div> {invoices.map((invoice) => ( <InvoiceCard key={invoice.id} invoice={invoice} /> ))} </div> ); } export default async function InvoiceCard({ invoice, }: { invoice: InvoiceCardProps }) { return ( <Card> {/* Divs showing invoice data */} <CardFooter> {invoice.id && ( <DeleteButton invoiceId={invoice.id} deleteInvoice={deleteInvoiceAction} /> )} </CardFooter> </Card> ); } **DeleteInvoice Server Action ** typescript "use server"; // imports and stuff export async function deleteInvoiceAction(invoiceId: number) { const deleted = await deleteInvoice(invoiceId); // db call to delete invoice return deleted.length > 0 ? deleted[0].id : null; } **DeleteButton Client Component** typescript // the server action is passed as prop from invoiceCard component export default function DeleteButton({ invoiceId, deleteInvoice, }: any) { const [open, setOpen] = useState(false); return ( {* 'Server action which was send via prop is triggered' *} <Button variant="destructive" onClick={async () => { await deleteInvoice(invoiceId); setOpen(false); }} > Delete </Button> ); }
use revalidatePath in server action
"use server";
// imports and stuff
export async function deleteInvoiceAction(invoiceId: number) {
  const deleted = await deleteInvoice(invoiceId); // db call to delete invoice

  if (deleted.length) {
    revalidatePath("/invoices")
  }
  return deleted.length > 0 ? deleted[0].id : null;
}
Answer