[GH-ISSUE #589] useActionState receives undefined state when Server Action calls redirect() #129

Closed
opened 2026-05-06 12:37:27 +02:00 by BreizhHardware · 0 comments

Originally created by @ayonli on GitHub (Mar 19, 2026).
Original GitHub issue: https://github.com/cloudflare/vinext/issues/589

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

  1. 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
}
  1. Use the action with useActionState in 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>
  );
}
  1. Submit the form. The Server Action runs, calls redirect(), and the component receives undefined as 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)
Originally created by @ayonli on GitHub (Mar 19, 2026). Original GitHub issue: https://github.com/cloudflare/vinext/issues/589 ## 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 1. Create a Server Action that calls `redirect()` on success: ```ts // 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 } ``` 2. Use the action with `useActionState` in a Client Component: ```tsx '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> ); } ``` 3. Submit the form. The Server Action runs, calls `redirect()`, and the component receives `undefined` as 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`: ```tsx 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`)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#129
No description provided.