Next.js Discord

Discord Forum

client component run 4 times

Unanswered
American black bear posted this in #help-forum
Open in Discord
American black bearOP
why am i redirecting four times ? here's my client component that's import from template.tsx

'use client'

import React, { useEffect,useState, useCallback } from "react"
import localForage from '@/config/localForage'
import { redirect } from 'next/navigation'

const Page = ({
    children,
  }: {
    children: React.ReactNode
}) => {

    const [user, setUser] = useState('')

    const getUser = useCallback(async () => {
        try {
          const value: string|null = await localForage.getItem('user');
          // This code runs once the value has been loaded
          // from the offline store.
          // console.log("user private", value);
            console.log(value)
            setUser(value!)

        } catch (err) {
          // This code runs if there were any errors.
          console.log(err);
        }
        console.log("end state")
      }, []);

      useEffect(() => {
        console.log("authorized layout")
        getUser()
        console.log("end state")
      },[])

    if (!user && user == null){   
        console.log("redirecting to login")
        redirect(('/login'))
    }else {
        return (
        <>
            {children}
        </>
        )
    }
}

export default Page

12 Replies

American black bearOP
firstly, can you try not in dev mode (next build && next start) as things are done many more times in dev
American black bearOP
uhmm i tried with the build option and it's minimized the redirecting to twice now
that's weird
that make sense
because dev mode runs you component code twice
Giant panda
Also the page shouldn't be a client side component. It can have unintended side-effects.
American black bearOP
uhmmm, the page, layout, and template is in server component that's importing a client component

this is template.tsx
import '@/assets/base.scss'
import type { Metadata } from 'next'
import { Inter,Roboto } from 'next/font/google'
import Layout from '@/app/(authorized)/_compo'

const inter = Inter({ subsets: ['latin'] })

export const metadata: Metadata = {
  title: 'SSO',
  description: 'Single-sign on system',
}

// const mainBody = inter.className +' ' + 'main-background'

export default function AuthorizedLayout({
  children,
}: {
  children: React.ReactNode
}) {

  console.log("authorized layout")

  return (
    <Layout>{children}</Layout>
  )

}
it's a workaround because next js need everything in server component, so i'll just make it as a wrapper to the actual layout that's a client component
it's not working honestly 😢
this is the _compo

'use client'

import React, { useEffect,useState, useCallback } from "react"
import localForage from '@/config/localForage'
import { redirect } from 'next/navigation'

const Page = ({
    children,
  }: {
    children: React.ReactNode
}) => {

    const [mounted, setMounted] = useState(false)
    const [user, setUser] = useState('')

    const getUser = useCallback(async () => {
        try {

            // localForage.setItem('user',"12345")
          const value: string|null = await localForage.getItem('user');
          // This code runs once the value has been loaded
          // from the offline store.
          // console.log("user private", value);
            console.log(value)
            setUser(value!)
            setMounted(true)

        } catch (err) {
          // This code runs if there were any errors.
          console.log(err);
        }
        console.log("end state1")
      }, []);

      useEffect(() => {
        console.log("authorized layout")
        getUser()
        console.log("end state2")
      }, [getUser]); 
      
    if (mounted){ 
        console.log("mounted")
        if (!user && user == null){   
            console.log("redirecting to login")
            redirect(('/login'))
        }else {
            return (
            <>
                {children}
            </>
            )
        }   
    }else {
        console.log("else")
        return null
    }
}

export default Page