Daniel Craciun
Daniel Craciun

Reputation: 149

Conditionally rendering UI based on cookies and supabase affects the rest of my program Next.js 13

I am trying to conditionally render an account button when a user is authenticated; render a login + sign-up button when the user is not authenticated as follows:

My DesktopBar.tsx file

import { getUser } from "@/app/_actions/userActions.ts"
import { NavItem } from "@/components/NavItem"

export async function DesktopBar() {
  const user = await getUser()
  return (
    <div className="hidden md:flex md:w-full md:justify-between md:p-6">
      <div className="flex items-center">
        <NavItem key="home" page="/" text="home" className="text-4xl" />
      </div>
      <div className="flex items-center">
        {user ? (
          <NavItem key="/account" page="/account" text="Account" />
        ) : (
          <>
            <NavItem key="/login" page="/login" text="Login" />
            <NavItem key="/sign_up" page="/sign_up" text="Sign Up" />
          </>
        )}
      </div>
    </div>
  )
}

My userActions.ts file



export async function getUser() {
     const { data: user } = await supabase
        .from("users")
        .select("name, is_admin")
        .single()
    return user
    
}

When running this code, everything works as expected when refreshing the page. When logged in, it displays Account in my navbar when I am authenticated before the JS loads as expected.

The problem arises when I try to use a custom search form component to navigate to a page that is generated via generateStaticParams().

My SearchForm.tsx file

"use client"

import { useRouter } from "next/navigation"

export function SearchForm() {
  const router = useRouter()

  function onSubmit(data) {
    router.push(`${data[0]}/${data[1]}/${data[2]}`)
  }

  return (
      <form onSubmit={onSubmit}>
        <Button type="submit">Search 🔍</Button>
      </form>
  )
}

This is a simple abstraction of the form, all you need to know is that it takes in three inputs from a select box, and then routes the user to that route via router.push().

The user is routed to this route: /[a]/[b]/[c]/page.tsx

import { FC } from "react"

export const revalidate = 20

interface pageProps {
  params: { a: string; b: string; c: string }
}


const page: FC<pageProps> = async ({ params }) => {
  const { a, b, c } = params
    // some logic happens...
}
// generate a combination of pages statically
export function generateStaticParams() {
  const combinations = []

  for (const a of letter1) {
    for (const b of letter2) {
      for (const c of letter3) {
        combinations.push({ a, b, c })
      }
    }
  }
  return combinations
}
export default page

When I comment out the generateStaticParams() method, everything seems to work. But I have lots of dynamic pages and still want to statically generate them at build time rather than navigating to them dynamically.

The error message I get is Dynamic Server usage: cookies. But I don't expect the code from Desktopbar.tsx to affect /[a]/[b]/[c]/page.tsx.

Finally, here is my root layout.tsx where I render the Desktop bar.

import "@/styles/globals.css"
import DesktopBar from "@/components/DesktopBar"


export default function RootLayout({ children }) {
  return (
    <html>
      <body className>
          <DesktopBar />
          <main>{children}</main>
      </body>
    </html>
  )
}

Upvotes: 3

Views: 346

Answers (2)

Andrew
Andrew

Reputation: 624

It's a little hard to understand exactly how you're putting this all together, especially since it doesn't show where exactly you're using cookies, but I think @thorwebdev was on the right track if this is even solvable with this structure. Try doing the opposite of what @thorwebdev recommended and setting export const dynamic = 'force-static', in places you want to, you know, force to be static, but know that this will cause cookies to break for its children. Using cookies will force things to be dynamic, and using generateStaticParams will try to force things to be static. If those two are nested, they're going to butt (but?) heads.

Upvotes: 0

thorwebdev
thorwebdev

Reputation: 1152

Try exporting the following from any routes that use the cookies function:

export const dynamic = "force-dynamic";

Upvotes: 0

Related Questions