Gabriel Izoton
Gabriel Izoton

Reputation: 43

How to stop Next.js from running client side code twice or hanging indefinitely when using the 'use client' directive?

The problem

I have a scenario that I must use the 'use client' directive because my project uses Chakra UI and their components can't render in the server.

When I try running this sample code:

// app/page.tsx

export async function getData() {
  const side = typeof window === 'undefined' ? 'server' : 'client'
  console.log(`I am running ${side} side!`)
  const dados = await Promise.resolve([{ name: 'Hi' }, { name: 'Hello' }])
  return dados
}

export default async function Home() {
  const data = await getData()
  return (
    <ul>
      {data.map(({ name }: any) =>
        <li key={name}>{name}</li>
      )}
    </ul>
  )
}

I receive the expected output in my terminal running the next development server:

I am running server side!

But when I add the 'use client' directive at the top of the file, I receive this duplicated message in my browser console:

I am running client side!   (2)

I understand that the 'use client' directive forces all the functions to be ran in the browser, but I can't understand why they run twice. This is a problem because in my real project the line that awaits the Promise makes a request to a back end and Next.js can't cache these requests, resulting in duplicated requests hitting the API.

What I tried

Multiple files

I tried to move the getData function to another file and ran the project:

// app/otherFile.ts

export async function getData() {
  const side = typeof window === 'undefined' ? 'server' : 'client'
  console.log(`I am running ${side} side!`)
  const dados = await Promise.resolve([{ name: 'Hi' }, { name: 'Hello' }])
  return dados
}
// app/page.tsx

import { getData } from './otherFile'

export default async function Home() {
  const data = await getData()
  return (
    <ul>
      {data.map(({ name }: any) =>
        <li key={name}>{name}</li>
      )}
    </ul>
  )
}

And, for my surprise, I saw this in my next development server

I am running server side!

and this in my browser console

I am running client side!   (2)

, making this hitting my API 3 times per page reload in my real application.

Experimental Server Actions

I also tried enabling 'Experimental Server Actions' in my next.config.js and added the 'use server' directive in app/otherFile.ts. When I try to reload the page, it hangs indefinitely and doesn't show any output.

Next steps?

Why does this happen and how can I avoid this behaviour? Is this possible?

I'm using Next.js 13.4.4 and React 18.2.0.

Upvotes: 4

Views: 8057

Answers (1)

rob9099
rob9099

Reputation: 79

You can test if it's React Strict mode causing the double render by disabling it in next.config.mjs

const nextConfig = {
 compiler: {
  styledComponents: {
    // Enabled by default.
    cssProp: true,
  },
 },
 reactStrictMode: false
};

Upvotes: 4

Related Questions