-
Notifications
You must be signed in to change notification settings - Fork 249
Description
Bug Description
When a Server Action used with useActionState calls redirect() (from next/navigation), the state returned by useActionState becomes undefined instead of retaining the previous state. This causes a TypeError on the next render if the component accesses any property on state.
Steps to Reproduce
- Create a Server Action that calls
redirect()on success:
// app/actions.ts
'use server';
import { redirect } from 'next/navigation';
import type { ActionResult } from './types';
export async function createPost(
_prev: ActionResult,
formData: FormData,
): Promise<ActionResult> {
// ... create post logic ...
redirect(`/posts/${postId}`); // <-- triggers the bug
}- Use the action with
useActionStatein a Client Component:
'use client';
import { useActionState } from 'react';
import { createPost } from './actions';
const initial = { success: false, error: '' };
export function PostForm() {
const [state, formAction, pending] = useActionState(createPost, initial);
// TypeError: Cannot read properties of undefined (reading 'success')
// state is `undefined` after redirect() is called
return (
<form action={formAction}>
{!state.success && state.error && <p>{state.error}</p>}
<button type="submit">Submit</button>
</form>
);
}- Submit the form. The Server Action runs, calls
redirect(), and the component receivesundefinedas the new state, crashing with:
TypeError: Cannot read properties of undefined (reading 'success')
Expected Behavior
When redirect() is called inside a Server Action, the browser should navigate to the target URL. The state value from useActionState should either retain the previous state or remain in a defined shape — it should never become undefined.
This is the standard Next.js behavior: redirect() throws a special internal error that Next.js catches to perform the navigation, and useActionState is not involved in that process.
Actual Behavior
state becomes undefined after redirect() is called in the Server Action, causing a TypeError on the next render.
Workaround
Avoid calling redirect() inside Server Actions used with useActionState. Instead, return a success payload from the action and navigate client-side using router.push() in a useEffect:
useEffect(() => {
if (state.success && state.data?.postId) {
router.push(`/posts/${state.data.postId}`);
}
}, [state, router]);Environment
- vinext: 0.0.31
-
- Next.js App Router (Server Actions)
-
-
- Cloudflare Workers (via
@cloudflare/vite-plugin)
- Cloudflare Workers (via
-