Implementing route protection

I tried implementing route protection in nextjs 13.4.4 but did not work as a user signs in but is not redirected to the protected pages , below is the codes privateroute.tsx
import { Spinner } from "@chakra-ui/react";
import { redirect, usePathname } from "next/navigation";


import { useUser } from "./middleware";


// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const WithPrivateRoute = (Component: React.FunctionComponent<any>) => {
const NewComponent = () => {
const { user, isLoading } = useUser();

// if (isLoading) return <Spinner />;
if (!user) redirect("/");

return <Component />;
};

return NewComponent;
};
import { Spinner } from "@chakra-ui/react";
import { redirect, usePathname } from "next/navigation";


import { useUser } from "./middleware";


// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const WithPrivateRoute = (Component: React.FunctionComponent<any>) => {
const NewComponent = () => {
const { user, isLoading } = useUser();

// if (isLoading) return <Spinner />;
if (!user) redirect("/");

return <Component />;
};

return NewComponent;
};
1 Reply
Revaycolizer
Revaycolizer13mo ago
middleware.tsx
import React, { createContext, useContext, useEffect, useState } from "react";
import type { Session, User } from "@supabase/supabase-js";
import { supabase } from "@/app/libs/supabase";
export const AuthContext = createContext<{
user: User | null;
session: Session | null;
isLoading: boolean;
}>({
user: null,
session: null,
isLoading: true,
});

export const AuthContextProvider = ({
children,
}: {
children: React.ReactNode;
}) => {
const [userSession, setUserSession] = useState<Session | null>(null);
const [user, setUser] = useState<User | null>(null);
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
void supabase.auth.getSession().then(({ data: { session } }) => {
setUserSession(session);
setUser(session?.user ?? null);
setIsLoading(false);
});

const { data: authListener } = supabase.auth.onAuthStateChange(
(event, session) => {
setUserSession(session);
setUser(session?.user ?? null);
setIsLoading(false);
}
);

return () => {
authListener.subscription.unsubscribe();
};
}, []);

const value = {
session: userSession,
user,
isLoading,
};

return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};

export const useUser = () => {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error("useUser must be used within a AuthContextProvider.");
}
return context;
};
import React, { createContext, useContext, useEffect, useState } from "react";
import type { Session, User } from "@supabase/supabase-js";
import { supabase } from "@/app/libs/supabase";
export const AuthContext = createContext<{
user: User | null;
session: Session | null;
isLoading: boolean;
}>({
user: null,
session: null,
isLoading: true,
});

export const AuthContextProvider = ({
children,
}: {
children: React.ReactNode;
}) => {
const [userSession, setUserSession] = useState<Session | null>(null);
const [user, setUser] = useState<User | null>(null);
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
void supabase.auth.getSession().then(({ data: { session } }) => {
setUserSession(session);
setUser(session?.user ?? null);
setIsLoading(false);
});

const { data: authListener } = supabase.auth.onAuthStateChange(
(event, session) => {
setUserSession(session);
setUser(session?.user ?? null);
setIsLoading(false);
}
);

return () => {
authListener.subscription.unsubscribe();
};
}, []);

const value = {
session: userSession,
user,
isLoading,
};

return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};

export const useUser = () => {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error("useUser must be used within a AuthContextProvider.");
}
return context;
};
layout.tsx
"use client"

// import Menu from "./menu"

import Navbar from "@/components/NavBar/Navbar"
import ClientOnly from "../../components/hydra/Hydra"




function RootLayout({children}
: {
children: React.ReactNode
}){
return (
<section>
<ClientOnly>
<main><Navbar/>{children}</main></ClientOnly>
</section>
)
}

export default WithPrivateRoute(RootLayout)

"use client"

// import Menu from "./menu"

import Navbar from "@/components/NavBar/Navbar"
import ClientOnly from "../../components/hydra/Hydra"




function RootLayout({children}
: {
children: React.ReactNode
}){
return (
<section>
<ClientOnly>
<main><Navbar/>{children}</main></ClientOnly>
</section>
)
}

export default WithPrivateRoute(RootLayout)