New Sep 18, 2024

Next.js 14 App Router: Code after return still executing, causing unexpected behavior

Libraries, Frameworks, etc. All from Newest questions tagged reactjs - Stack Overflow View Next.js 14 App Router: Code after return still executing, causing unexpected behavior on stackoverflow.com

Issue: I'm encountering an issue in a Next.js 14 App Router project where code after a return statement is still being executed, even though the condition for returning a component is met. This behavior causes unexpected side effects such as extra API calls being made after the return.

Note: This issue occurs only when deployed on Vercel. The same code works as expected in my local environment without any issues.


Context: I'm using Next.js 14 App Router for a page that handles user pre-registration. In this flow, after a user submits the form, the registration ID is saved in a cookie, and the user is redirected to a confirmation message page, indicating the next steps. The confirmation message page should return a success message informing the user that a confirmation email has been sent, and the function should stop executing any further code.

This behavior works as expected in my local environment, but on the server (Vercel), code after the return statement continues to execute, triggering unintended API requests.

Here is the relevant portion of the code:

export default async function Page({ searchParams }) {
  console.log(typeof window === 'undefined' ? 'Server-side render' : 'Client-side render');

const regToken = searchParams.regToken; const cookieStore = cookies(); const authToken = cookieStore.get('auth_token')?.value; let regId = null;

const reqOptions = { ...(regToken && { method: 'POST' }), // Corrected from emailRegToken to regToken 'Content-Type': 'application/json', headers: { Authorization: Bearer ${authToken} }, };

console.log({ regToken });

if (regToken) { const apiUrl = ${process.env.MY_API_URL}/api/finalizeRegistration?registrationToken=${encodeURIComponent(regToken)}; // Corrected to use regToken const finalizeRegRes = await fetch(apiUrl, reqOptions); const finalizeRegData = await finalizeRegRes.json(); regId = finalizeRegData[0]?.registrationId; } else { const registrationId = cookieStore.get('registration_Id')?.value;

try { const parsedData = JSON.parse(registrationId); regId = parsedData.registrationId; } catch (error) { regId = null; } }

// Return success page if condition is met if (regId === -1 && !regToken) { // Updated emailRegToken to regToken console.log('Condition met: regId === -1 and !regToken'); return ( <SuccessPage title="Thank you! A confirmation email is on its way." buttonHref="/events" buttonCTA="Back to events" message="Please check your inbox and follow the instructions to complete your registration." /> ); }

console.log('This should not be logged if regId === -1 and !regToken');

// Additional API fetches const registrationResponse = await fetch(${process.env.MY_API_URL}/api/Events/registration?registrationId=${regId}, { // Updated to use MY_API_URL headers: { Authorization: Bearer ${authToken} }, }); const registrationData = await registrationResponse.json();

const { eventId, name: PatronName } = registrationData[0];

const eventResponse = await fetch(${process.env.MY_API_URL}/api/Events/event?tokenId=${eventId}, { // Updated to use MY_API_URL headers: { Authorization: Bearer ${authToken} }, }); const eventData = await eventResponse.json();

return ( <SuccessPage title="You've been successfully registered!" buttonHref="/events" buttonCTA="Back to events" > <Box mt={4}> <Card sx={{ minWidth: 275 }}> <CardContent sx={{ padding: 0 }}> <Box mb={2}> <CustomCardImageContainer imageUrl={eventData[0]?.image[0]}> {!eventData[0]?.image[0] && <CardDefaultIcon icon={LibraryBooks} fontSize="cardSize" />} </CustomCardImageContainer> </Box> <Typography variant="h5">{eventData[0]?.name}</Typography> <Typography variant="h6" gutterBottom> {PatronName} </Typography> <EventTimeFrame sessions={eventData[0]?.event[0]?.sessions} /> <EventSessions sessions={eventData[0]?.event[0]?.sessions} /> <Typography variant="body2" mt={2}> {eventData[0]?.event[0]?.locationDetail} </Typography> </CardContent> </Card> </Box> </SuccessPage> ); }


What I Expect:

When the condition regId === -1 && !emailRegToken is met, I expect the function to stop further execution after the return, and the additional API calls should not be made.


What Actually Happens:

Even though the condition is met and the return happens, the log statement "This should not be logged if regId === -1 and !emailRegToken" still gets logged, indicating that the function keeps executing, and the API calls are still made.


Debugging Attempts:

  1. I added logs before and after the return statement to confirm the condition was met and the return was reached.
  2. I logged whether the code was running on the server-side or client-side using typeof window === 'undefined', and it confirmed the function was running server-side.
  3. I suspect double execution might be happening due to SSR and client-side hydration, but I can’t pinpoint exactly what’s causing it.

Environment:


Logs from my local:

enter image description here


Logs from Vercel: Below are the logs that were recorded on Vercel, highlighting the problem:

responseStatusCode requestUserAgent level message
-10 Vercel Edge Functions error TypeError: Cannot destructure 'eventId' as it is undefined.
-10 Vercel Edge Functions error TypeError: Cannot destructure 'eventId' as it is undefined.
-10 Vercel Edge Functions info This should not be logged if regId === -1 and !emailRegToken
-10 Vercel Edge Functions info null true
-10 Vercel Edge Functions info false true
-10 Vercel Edge Functions error Invalid JSON format: "undefined" is not valid JSON
-10 Vercel Edge Functions info { registrationId: undefined }
-10 Vercel Edge Functions info { emailRegToken: undefined }
-10 Vercel Edge Functions info Server-side render
500 Vercel Edge Functions error [GET] confirmation-message... status=500
-10 Chrome/128.0 Safari/537.36 info Returning SuccessPage, code should stop here
-10 Chrome/128.0 Safari/537.36 info regId: -1 emailRegToken: undefined
-10 Chrome/128.0 Safari/537.36 info Condition met: regId === -1 and !emailRegToken
-10 Chrome/128.0 Safari/537.36 info -1 true
-10 Chrome/128.0 Safari/537.36 info true true
-10 Chrome/128.0 Safari/537.36 info { regId: -1 }
-10 Chrome/128.0 Safari/537.36 info { parsedData: { registrationId: -1 } }
-10 Chrome/128.0 Safari/537.36 info { registrationId: '{"registrationId":-1}' }
-10 Chrome/128.0 Safari/537.36 info { emailRegToken: undefined }
-10 Chrome/128.0 Safari/537.36 info Server-side render
-10 Chrome/128.0 Safari/537.36 info Returning SuccessPage, code should stop here
-10 Chrome/128.0 Safari/537.36 info regId: -1 emailRegToken: undefined
-10 Chrome/128.0 Safari/537.36 info Condition met: regId === -1 and !emailRegToken
-10 Chrome/128.0 Safari/537.36 info -1 true
-10 Chrome/128.0 Safari/537.36 info true true
-10 Chrome/128.0 Safari/537.36 info { regId: -1 }
-10 Chrome/128.0 Safari/537.36 info { parsedData: { registrationId: -1 } }
-10 Chrome/128.0 Safari/537.36 info { registrationId: '{"registrationId":-1}' }
-10 Chrome/128.0 Safari/537.36 info { emailRegToken: undefined }

My Question:

Why is the code after the return still being executed? How can I prevent this double execution or ensure that the code after the return doesn’t run once the condition is met?

Scroll to top