Next.js Discord

Discord Forum

understanding loading.js

Unanswered
HOTCONQUEROR posted this in #help-forum
Open in Discord
'use client';

import {useState,useEffect,createContext} from 'react'
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";

//  for all routes this layout should be for navigation side bar and footer.

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

export const AuthContext = createContext({status:false})

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {

  const [isAuth,setIsAuth] = useState<{status:boolean}>({status:false})
 

  useEffect(()=>{
    fetch('http://127.0.0.1:8000/checkauth/',{method:'GET',credentials:'include'}).then((res)=>{
      res.json().then((data)=>{
        console.log(data)
        setIsAuth(data)
      })
    })

  },[isAuth.status])
  return (
    isAuth &&
    <html lang="en">
       <AuthContext.Provider value={isAuth}>
      <body className={inter.className}>{children}</body>
      </AuthContext.Provider>
    </html>
  );
}


the above is layout.js which is used to check if user is authenticated


export default function LoadAuth(){
    return(
        <div className='skeleton'>Loading...</div>
    )

}
this is loading.js for some page

the problem i am facing here is that when i load the page, it shows "user not authenticated" for a seconds, then the isAuth state is actually set after that second, however during that moment loading.js isn't rendering, instead i get the conditional flickering.

49 Replies

could you please show your file structure?
btw, the loading.tsx inside notes folder
Besides that, its very bad practice to mark layout.js as client component
it'll execute all the js on the client side instead if server which is the default and faster way
@Naeemgg it'll execute all the js on the client side instead if server which is the default and faster way
how am i supposed to use useEffect to see if user is auth or not?
are you using next-auth?
i am simply just making a request to backend to check if user is auth or not
create another file for example providers.tsx same level as layout.tsx and wrap the {children} with it
I believe your problem will be solved
because the way you used createContext is not a good approach towards it
@Naeemgg because the way you used `createContext` is not a good approach towards it
i get that i just need to call the component of providers.tsx into layout.tsx render
Yep and instead of useEffect you can do something like this
async function userAuth() {
  const res = await fetch('https://api.example.com/...')
  .........other things....
 
  if (!res.ok) {
    throw new Error('Failed to fetch data')
  }
 
  return res.json()
}
 
export default async function Page() {
  const data = await userAuth()
 
  return <ClientComponent auth={data.user}/>
}
on client side you just need to check if user is present in session or not
that needs to be handled from the backend, if the user is in session then it will get session object containing user details like name,email or whatever you've set. Otherwise null or empty object or better false which means user is not authorised
If you're doing it first time with nextjs its better to go with next-auth
its easy to setup and has good docs
nah, i won't bother with adding a new package for now
@HOTCONQUEROR no, i am asking, how did you come up with `auth` prop here?
you need to render 2 different things according to user auth status thats why you need something client side to let you know if user is in session or not
lets say this is client component
import React from 'react'

const check = ({auth}:Auth) => {
  return (
    <div>
      {auth.user? <h1>Super secret details</h1>:<h1>You are not authorized.</h1>}
    </div>
  )
}

export default check
@Naeemgg correct
there is a reason why i was using useContext api... didn't want to end up with prop drilling
well, i mean, it is not drilling in the literal context, but still
yeah you can add it to context also
I totally forgot you were using context api
@Naeemgg I totally forgot you were using context api
your approach make me avoid using client component basically

anyway, after i create the provider component in the same level of layout file, this should be included in children prop of layout, right?
but still you need to pass it down to atleast on child component in order to add it to context because you can't do it in server component
 <html lang={params.lang}>
      <head />
      <body className={inter.className}>
        <ContextProvider>
        {children}
        </ContextProvider>
      </body>
    </html>
@Naeemgg Yes
i tried this appraoch
'use client';
import { createContext,useState } from "react";


export const AuthContext = createContext({status:false})

export default function CheckAuth(){

  const [isAuth,setIsAuth] = useState<{status:boolean}>({status:false})
  console.log(isAuth)
  fetch('http://127.0.0.1:8000/checkauth/',{method:'GET',credentials:'include'}).then((res)=>{
    res.json().then((data)=>{
      setIsAuth(data)
    })
  })


  return (
    isAuth &&
       <AuthContext.Provider value={isAuth}>
      </AuthContext.Provider>
  );
}
provider.tsx
layout.tsx:

import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";

//  for all routes this layout should be for navigation side bar and footer.

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

/*export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};
*/


export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body className={inter.className}>{children}</body>
    </html>
  );
}
'use client';
import { createContext,useState } from "react";


export const AuthContext = createContext({status:false})

export default function CheckAuth({children}:{children:ReactNode}){

  const [isAuth,setIsAuth] = useState<{status:boolean}>({status:false})
  console.log(isAuth)
  fetch('http://127.0.0.1:8000/checkauth/',{method:'GET',credentials:'include'}).then((res)=>{
    res.json().then((data)=>{
      setIsAuth(data)
    })
  })


  return (
    isAuth &&
       <AuthContext.Provider value={isAuth}>
  {children}
      </AuthContext.Provider>
  );
}
you need to pass children in it also
in order to use it within your app you need to wrap children i,e whole app with it
make sense
@Naeemgg in order to use it within your app you need to wrap children i,e whole app with it
i tried logging something in provider file, but nothing is being logged
and it is always false for being auth