Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

redirect on the server (server action) causes page double render #57257

Closed
1 task done
benoitgrelard opened this issue Oct 23, 2023 · 26 comments · Fixed by #63786
Closed
1 task done

redirect on the server (server action) causes page double render #57257

benoitgrelard opened this issue Oct 23, 2023 · 26 comments · Fixed by #63786
Labels
bug Issue was opened via the bug report template. locked Navigation Related to Next.js linking (e.g., <Link>) and navigation.

Comments

@benoitgrelard
Copy link

Link to the code that reproduces this issue

https://github.com/benoitgrelard/next-redirect

To Reproduce

  1. Start the application in dev mode (npm run dev)
  2. Redirect to the /email page using the different ways provided on the page and note the logs in the terminal (server side)

Current vs. Expected behavior

Current:

  1. Calling redirect inside the server action seems to cause a double render (you see a double log)
  2. Calling redirect on the client only causes one render (although I sometimes also see 0 logs… 🤔)
  3. Clicking on the link to the /email page only causes one render (you see one log)
  4. Loading/re-loading the /email page directly only shows one log

Another thing I've noticed that I don't quite understand: Once on the /email page, and using the back button to browse back history:

  • using the redirect on the client button won't log anything (no render?)
  • using the link won't log anything either
  • using redirect on the server always still logs twice

Expected:

  • Considering the /email page is a React server component, I expect it to only be rendered once.

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 23.0.0: Fri Sep 15 14:41:43 PDT 2023; root:xnu-10002.1.13~1/RELEASE_ARM64_T6000
Binaries:
  Node: 18.16.1
  npm: 9.5.1
  Yarn: 1.22.18
  pnpm: N/A
Relevant Packages:
  next: 13.5.6
  eslint-config-next: 13.5.6
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.2.2
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

App Router, Routing (next/router, next/navigation, next/link)

Additional context

No response

@benoitgrelard benoitgrelard added the bug Issue was opened via the bug report template. label Oct 23, 2023
@github-actions github-actions bot added the Navigation Related to Next.js linking (e.g., <Link>) and navigation. label Oct 23, 2023
@Syedhussainsaber
Copy link

@benoitgrelard can you assign me this issue? I will work on this

@benoitgrelard
Copy link
Author

@Syedhussainsaber It doesn't look like I can.

CleanShot 2023-10-23 at 15 13 18@2x

@OtisTemler
Copy link

Yes, can confirm. Same behaviour here.

@MichaelJohnson144
Copy link

Yes, can confirm. Same behaviour here.

So can I.

@JulianJorgensen
Copy link

I can also reproduce this issue 👍🏻

@wingy3181
Copy link

wingy3181 commented Nov 7, 2023

EDIT: didn't see there was already a repository with example...here is another example i guess

Reproduced as well for me
Have created example repository with the issue at https://github.com/wingy3181/redirect-double-render-server-component-example

Navigate to http://localhost:3000/from and click on the button "Redirect to"

I see the following log from the server

> redirect-double-render-server-component-example@0.1.0 dev
> next dev

   ▲ Next.js 14.0.1
   - Local:        http://localhost:3000

 ✓ Ready in 13.7s
 ○ Compiling /from/page ...
 ✓ Compiled /from/page in 7.2s (479 modules)
FromPage
 ✓ Compiled in 1264ms (218 modules)
 ○ Compiling /favicon.ico/route ...
 ✓ Compiled /to/page in 2.9s (486 modules)
ToPage

FromPage
handleAction
ToPage
ToPage
^C

@kirankulkarni
Copy link

We have been observing this issue in NextJS 14 in production. Is there a workaround for this?

@N-Digital-LLC
Copy link

same here. At least we can rely on the Next cache not making two API calls to the backend when the server component re-renders.

@OtisTemler
Copy link

OtisTemler commented Jan 15, 2024

Just checked, bug still exists even in latest 14.1.0

@smozely
Copy link

smozely commented Jan 25, 2024

same here. At least we can rely on the Next cache not making two API calls to the backend when the server component re-renders.

@N-Digital-LLC is that actually working for you? in my attempts the server is still being hit twice, even when I tried wrapping things in React.cache

Or anyone else got a work around? It bit us because of a race condition in our API lazily generating a CSRF token meant we got a different token for the each request, and then used the wrong one. (We've disabled that lazy generation "feature" now)

@OtisTemler
Copy link

Nope, no work around yet, just randomly renders twice after a server side redirect no matter what.

My use case: I've some app pages which might do a server-side redirect depending of the result of an GET request (server-side) on that page. The redirect works and then triggers a re-render at the resulting / redirected page, causing a beautiful UI flickering / re-render.

Basically @wingy3181 already has a nice basic repro posted.

@gukin-han
Copy link

@smozely It works for me. I use cache fetch to call external api. Even if it's going to call "next server" twice, but my spring backend doesn't have to react to this call because data cache in next server will do the job.

@JulianJorgensen
Copy link

I just reproduced it using @wingy3181s repo and upgraded to Next v14.1.0. Super weird this issue remains! Seems its a very fundamental issue to Next. I love the framework, that's why it's so baffling to me this issue isn't prioritised or even addressed!
I have multiple server components that trigger some important API code when mounted. That code is obviously run twice, and I end up with duplicated data.

I can also confirm this issue seems to exist also on non-serveraction redirects to a server component.

Thanks for all the repos reproducing this very clearly.

@robbiemccorkell
Copy link

I am also having the same issue on 14.1.0. On my project I have a server rendered home page on / that checks some details on the database and then redirects the user to one of two pages. Both pages have their own async fetches on the server side, and result in the double render as described.

My workaround is to perform the initial redirect on the client side in a side effect. For example:

page.tsx

import HomeRedirect from "./HomeRedirect";

export default async function Home() {
  return <HomeRedirect />;
}

HomeRedirect.tsx

"use client";
import { redirect, useRouter } from "next/navigation";

export default function HomeRedirect() {
  const router = useRouter();

  useEffect(() => {
    redirect("/other-page");
  }, [router]);

  return null;
}

With this I see a flash of the loading component, but the second page is rendered only once so it looks much less ugly.

My only other workaround would be to move all data fetching to the client side of the pages being redirected to. But this would be a huge hassle and defeat the purpose of server components.

@sergitejada
Copy link

Have the same issue

"use server"

import { getToken } from "@/lib/auth"
import { revalidatePath } from "next/cache"
import { redirect } from "next/navigation"

const url = `${process.env.AUTH_PUBLIC_BAKEND_URL}/api/users/clients`

function checkAddress(formData) {
  const address = formData.get("address")
  const town = formData.get("town")
  const zip_code = formData.get("zip_code")
  const province = formData.get("province")
  const country = formData.get("country")

  const isAddressEmpty = !address && !town && !zip_code && !province && !country

  if (!isAddressEmpty) {
    return {
      address,
      town,
      zip_code,
      province,
      country,
    }
  }
}

export async function createClient(prevState, formData) {
  const token = await getToken()

  const clientData = {
    client: {
      name: formData.get("name"),
      first_name: formData.get("first_name"),
      last_name: formData.get("last_name"),
      email: formData.get("email"),
      phone: formData.get("phone"),
      tags_names: formData.getAll("tags_names"),
    },
  }

  if (checkAddress(formData)) {
    clientData.client.addresses_attributes = [checkAddress(formData)]
  }

  const response = await fetch(url, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json",
      Authorization: token,
    },
    body: JSON.stringify(clientData),
  })

  const responseBody = await response.json()

  if (responseBody.status == "created") {
    revalidatePath("/dashboard/usuarios/clientes")
    redirect(`/dashboard/usuarios/clientes/${responseBody.data.id}`)
  } else {
    return responseBody.errors
  }
}

Double Get caused by redirect
image

@bvaughn
Copy link

bvaughn commented Mar 10, 2024

Stumbled upon this issue after seeing the same thing happen with a very basic redirect on a new NextJS 14 app. Also pretty surprising that this happens, considering how noticeable it is in production.

FWIW I ended up going with the workaround mentioned by @robbiemccorkell above (thanks!)

@samurodriguez
Copy link

A few months ago I had to downgrade because of a critical bug (#56018). Now I want to update to a newer version, but I find this redirect thing... Lately, Next.js has been surprising me with the number of bugs and how long it takes to fix them 🙁

@JulianJorgensen
Copy link

Could this issue be related to this #62561?

@thereis
Copy link

thereis commented Mar 25, 2024

I still face this issue here with a server component redirecting the client to a different route.

I am usingnext@14.1.4.

@petejodo
Copy link

petejodo commented Mar 27, 2024

Could this issue be related to this #62561?

tested 14.2.0-canary.44 (which includes that PR) and the issue still occurs

@thexpand
Copy link

@ztanner, does #63786 fix this issue as well?

@ztanner
Copy link
Member

ztanner commented Mar 30, 2024

Yes, looks like this was resolved in #63786, which is available as of v14.2.0-canary.48.

I cloned the original repro and it appears to work as expected, so I'm going to close this out. Happy to investigate if people are still running into this behavior!

CleanShot.2024-03-30.at.08.07.02.mp4

@ztanner ztanner closed this as completed Mar 30, 2024
@thexpand
Copy link

Amazing, thanks! Is there a planned release date for v14.2.0?

@moomooberry
Copy link

moomooberry commented Apr 8, 2024

until to fix this issue,
try useRouter in client side

in Page.tsx

"use client";

import { FC, MouseEventHandler } from "react";
import authLoginAction from "./_action";
import { useRouter } from "next/navigation";

const AuthLoginPage: FC = () => {
  const { back } = useRouter();

  const onSubmitClick: MouseEventHandler<HTMLButtonElement> = () => {
    back();
  };

  return (
    <div>
      <form action={authLoginAction}>
        <label>
          id
          <input name="id" />
        </label>
        <label>
          password
          <input name="password" />
        </label>
        <button type="submit" onClick={onSubmitClick}>
          submit
        </button>
      </form>
    </div>
  );
};

export default AuthLoginPage;

I can't use redirect method in action.ts due to this twice render issue.
just set token in server action and route in client side.

hope to fix this issue

@thexpand
Copy link

This is still not fixed in 14.2.1... The component that the user is being redirected to is again, in fact, rendered twice.

Copy link
Contributor

github-actions bot commented May 1, 2024

This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot added the locked label May 1, 2024
@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 1, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue was opened via the bug report template. locked Navigation Related to Next.js linking (e.g., <Link>) and navigation.
Projects
None yet
Development

Successfully merging a pull request may close this issue.