Skip to content

Conversation

@ramonmalcolm10
Copy link

When using useAction or useOptimisticAction with server actions that call redirect(), the redirect fails when Next.js
cacheComponents option is enabled.

Proposed changes

Problem

When using useAction or useOptimisticAction hooks with server actions that call redirect() from Next.js, the redirect fails to execute when the Next.js cacheComponents feature is enabled.

Root Cause

The library was catching navigation errors (from redirect(), notFound(), etc.) and storing them in React state, then re-throwing them later in a useLayoutEffect hook. This deferred error handling created a timing issue:

  1. Server action calls redirect(), throwing a navigation error
  2. Client-side hook catches the error and stores it in state
  3. Function returns without re-throwing
  4. Later, useLayoutEffect tries to re-throw the error

With cacheComponents enabled, Next.js caches and restores component trees during React transitions. The component state could be restored from cache before the useLayoutEffect runs, causing the redirect to be cancelled or ignored.

Solution

Modified the hooks to throw navigation errors immediately (synchronously) when caught in the promise chain, instead of deferring them to useLayoutEffect.

What Changed:

  • 4 locations in hooks.ts: Changed navigation error handling from setNavigationError(e); return; to setNavigationError(e); throw e;
  • 1 location in hooks-utils.ts: Removed redundant error re-throwing since errors are now thrown immediately

Related issue(s) or discussion(s)

re #393


@vercel
Copy link

vercel bot commented Oct 27, 2025

@ramonmalcolm10 is attempting to deploy a commit to the Edoardo Ranghieri's projects Team on Vercel.

A member of the Team first needs to authorize it.

@MeesEgberts
Copy link

@TheEdoRan could you review this when possible? I can help if needed — it’s currently blocking my progress.

@programming-with-ia

This comment was marked as spam.

@imbhargav5
Copy link

Not to brag. But I had a hypothesis on useLayoutEffect and thought it could be causing problems. And I forked next-safe-action into a new repo and tried it, several of my problems with cached components went away. I create a new package from the fork called next-cool-action. I am not sure if it is the best approach and if the useLayoutEffect had a real importance with a few edge cases and if there was something I missed, but thought let me first release and test it in my apps. Seemed to work nice.

Anyway, I published it here and gave credit to next-safe-action and also mentioned how it is different from next-safe-action. https://www.npmjs.com/package/next-cool-action It is a 2 day old package, but please try it and see if the bugs go away.

FYI: All navigations events from server actions are working fine, there were some server actions which were just hanging in the loading state in a bizarre way in cache components, which I couldn't make head or tails of, and I didn't see that issue in next-cool-cache after moving away from useLayoutEffect. All the existing tests pass too.

I didn't test this with nextjs apps which didn't have cacheComponents enabled. At this point it is an experiement and did it since I was blocked.

@programming-with-ia
Copy link

@imbhargav5 see: better-next-actions

@imbhargav5
Copy link

@programming-with-ia I like next-safe-action better because a)powerful test cases, b) supports zod schemas and standardjson schema, type inference is better as opposed to payload:any c) better-next-actions also is nice but is a bit light for my liking and only a thin wrapper over startTransition, and useState, and the types can be improved a bit. Thanks for sharing though!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants