How to cancel a server action? #54516
Replies: 12 comments 11 replies
-
As far as I know, when the actions are sent to the server, you can't undo them or affect them from outside. |
Beta Was this translation helpful? Give feedback.
-
Any updates on this? |
Beta Was this translation helpful? Give feedback.
-
This would be useful I think. |
Beta Was this translation helpful? Give feedback.
-
This would be useful especially with strict mode when useEffect runs twice in a row. |
Beta Was this translation helpful? Give feedback.
-
waiting for updates on this as well |
Beta Was this translation helpful? Give feedback.
-
we need can cancel server actions! |
Beta Was this translation helpful? Give feedback.
-
I am currently on a similar issue. Earlier with fetch('/api/...') and the like I was creating an AbortController in the mount effect, then doing the fetch with the related abortSignal and returning a destructor from the effect which aborts the abortController and so the fetch. Now, with server actions, I will do the following:
Simple example:
|
Beta Was this translation helpful? Give feedback.
-
Hi All, I am also looking for the prevention of api's. Is there any issue on this because I created a sandbox example but and tried some work around but didn't work at all, could you please suggest me what's the work around if you get the solution... sandbox URL: sandbox I am using nextjs - 15, with react 19 'use server';
import { setTimeout } from 'timers/promises';
type ActionId = number;
interface ActionResponse {
success: boolean;
error?: string;
}
const activeActions: Map<ActionId, boolean> = new Map();
export async function handleAction(data: Record<string, unknown>, id: ActionId): Promise<ActionResponse> {
activeActions.set(id, true);
try {
for (let i = 0; i < 10; i++) {
if (!activeActions.get(id)) {
throw new Error('Action aborted');
}
console.log(`Processing step ${i + 1}`);
await setTimeout(1000); // Simulated delay
}
return { success: true };
} catch (error) {
return { success: false, error: error instanceof Error ? error.message : 'Unknown error' };
} finally {
activeActions.delete(id);
}
}
export async function abortAction(id: ActionId) {
activeActions.set(id, false);
}
and the component is "use client";
import { useTransition, useState } from "react";
import { handleAction, abortAction } from "../server";
type ActionId = number;
interface ActionResponse {
success: boolean;
error?: string;
}
export default function MyComponent() {
const [isPending, startTransition] = useTransition();
const [actionId, setActionId] = useState<ActionId | null>(null);
function startAction(): void {
const id: ActionId = Date.now();
setActionId(id);
startTransition(() => {
handleAction({ key: "value" }, id)
.then((res: ActionResponse) => {
if (res.success) {
console.log("Action completed");
} else {
console.log("Action aborted or failed:", res.error);
}
})
.finally(() => setActionId(null));
});
}
function stopAction(): void {
if (actionId !== null) {
abortAction(actionId);
setActionId(null);
}
}
return (
<div>
<button onClick={startAction} disabled={isPending || actionId !== null}>
Start Action
</button>
<button onClick={stopAction} disabled={actionId === null}>
Abort Action
</button>
</div>
);
}
|
Beta Was this translation helpful? Give feedback.
-
what happens if you just do |
Beta Was this translation helpful? Give feedback.
-
any update on this? The only non-hacky workaround I find currently is to create a specific Route Handler instead of relying on server actions, and hit the endpoint with |
Beta Was this translation helpful? Give feedback.
-
hi, everyone is there any update on it? |
Beta Was this translation helpful? Give feedback.
-
I just ran into the same issue and find it really strange that there is no solution for this. The point of the server action is that I can run it on the server as a regular function and on the client as a fetch call. But when used on the front, it doesn't support one of the basic fetch features, so now I have to either make a route handler which calls the action from the server (makes my thinking - why do server actions even exist?) or I need to make a post request to the corresponding server action url, which creates a vector for failure (especially as there is no documentation on how the url is generated). With both of these options I loose type safety, so I'd have to write another batch of unnecessary types and exports. Or, I have to write some weird logic on the front end to ignore the responses of the calls which should have been canceled. Ignoring the fact that neither of these options actually stops the execution of whatever is running on the server (this is actually not relevant to my use case, but might be for others). Seeing that there is not even an acknowledgment of this issue after two years, I can deduct that we will never see this implemented - adding just another annoyance to deal with a framework which is supposed to make my life easier. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Summary
I am ramping up on server actions and I was trying to understand if there is a way to cancel them?
Let's say have an action that can take several seconds to run and you want to give the opportunity to the user to cancel the action.
With
fetch
you could useAbortController
to do that, but I couldn't find anything on that topic regarding server actions.Does anyone know?
Additional information
No response
Example
No response
Beta Was this translation helpful? Give feedback.
All reactions