understanding loading.js
Unanswered
HOTCONQUEROR posted this in #help-forum
'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 pagethe 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 folderBesides that, its very bad practice to mark layout.js as client component
@Naeemgg Besides that, its very bad practice to mark layout.js as client component
interesting , why is that
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 itI 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 renderYep 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
@Naeemgg Yep and instead of useEffect you can do something like this
tsx
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}/>
}
that would be included in layout.js if it is on the same level of the file
ok i will try that and come back to you in a min
@Naeemgg Yep and instead of useEffect you can do something like this
tsx
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}/>
}
wait, here we are trying to fetch from the backend if user is auth or not, and i am not sure what with
ClientComponent having auth prop here?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@Naeemgg 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
no, i am asking, how did you come up with
auth prop here?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
@Naeemgg 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
are you implying i need to pass
auth prop to the client component?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 drillingwell, 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
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.tsxlayout.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 alsoin 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 loggedand it is always
false for being auth