From cdb2a15643178c108cf54657b773b14605177992 Mon Sep 17 00:00:00 2001 From: kovakmedya Date: Fri, 22 May 2026 01:15:32 +0300 Subject: [PATCH] fix(ui): router.refresh after server actions so status updates show without reload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lab side reported that after accepting a job / advancing a step the button kept its 'Yükleniyor' state and the page didn't reflect the new status until they hit refresh. Two issues stacked on top of each other: 1. The button forms were passing the action through an extra startTransition wrap — 'action={(fd) => startTransition(() => action(fd))}'. With React 19 + useActionState this is unnecessary; useActionState already manages its own transition. The double transition can leave the dispatch's pending flag wedged in some race orderings, which matches what the user saw. 2. revalidatePath() on the server invalidates the RSC cache but does not trigger client navigation. So even after the action returned, the page kept rendering the stale Job snapshot — and since the buttons are conditional on job.status, the now-stale 'pending' status meant the button stayed visible. Fix in JobActionsPanel and the four sibling components (connections delete row, pending inbound, pending outbound, file row delete): - Removed the startTransition wrap; forms point at 'action' directly. - Added useRouter() and call router.refresh() in the same useEffect branch where the success toast fires. This forces the Server Component tree to re-fetch, picks up the new job.status, and the actions panel rerenders into whatever button is next in the flow. - Cleaned the now-unused useTransition imports. Net effect: tap 'İşleme Al' → spinner appears, ~400ms later the toast hits and the row updates in place to 'Sonraki Aşama' without any manual refresh. --- .../components/connections-table.tsx | 14 ++--- .../components/pending-inbound-table.tsx | 37 +++++------ .../components/pending-outbound-table.tsx | 21 ++++--- .../[jobId]/components/job-actions-panel.tsx | 62 +++++++++---------- .../[jobId]/components/job-files-panel.tsx | 13 ++-- 5 files changed, 69 insertions(+), 78 deletions(-) diff --git a/src/app/(dashboard)/connections/components/connections-table.tsx b/src/app/(dashboard)/connections/components/connections-table.tsx index f0c0dab..a6652ff 100644 --- a/src/app/(dashboard)/connections/components/connections-table.tsx +++ b/src/app/(dashboard)/connections/components/connections-table.tsx @@ -1,7 +1,8 @@ "use client"; import * as React from "react"; -import { useActionState, useEffect, useState, useTransition } from "react"; +import { useActionState, useEffect, useState } from "react"; +import { useRouter } from "next/navigation"; import { Loader2, Trash2 } from "lucide-react"; import { toast } from "sonner"; @@ -108,17 +109,18 @@ function ApprovedRow({ deleteConnectionAction, initialConnectionActionState, ); - const [, startTransition] = useTransition(); + const router = useRouter(); const [open, setOpen] = useState(false); useEffect(() => { if (state.ok) { toast.success("Bağlantı silindi."); setOpen(false); + router.refresh(); } else if (state.error) { toast.error(state.error); } - }, [state]); + }, [state, router]); const kindLabel = row.counterpart?.kind === "lab" @@ -190,11 +192,7 @@ function ApprovedRow({ -
{ - startTransition(() => action(fd)); - }} - > +
-
{ - startTransition(() => rejectAction(fd)); - }} - > + - { - startTransition(() => action(fd)); - }} - > +