I'm trying to build something with react that has some protected routes.
My main.jsx file:
import React from "react";
import ReactDOM from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import "./index.css";
import store from "./app/store";
import { Provider } from "react-redux";
import Root from "./components/Root";
import PublicLayout from "./components/PublicLayout";
import PersistLogin from "./components/PersistLogin";
import RequireAuthLayout from "./components/RequireAuthLayout";
import { ErrorPage, Home, Login, Logout, Register } from "./pages";
const router = createBrowserRouter([
{
path: "/*",
element: <Root />,
errorElement: <ErrorPage />,
children: [
{
element: <PublicLayout />,
children: [
{ path: "login", element: <Login /> },
{ path: "register", element: <Register /> },
],
},
{
element: <PersistLogin />,
children: [
{
element: <RequireAuthLayout />,
children: [
{ path: "home", element: <Home /> },
{ path: "logout", element: <Logout /> },
],
},
],
},
],
},
]);
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<Provider store={store}>
<RouterProvider router={router} />
</Provider>
</React.StrictMode>
);
Root.jsx:
import React from "react";
import { Outlet } from "react-router-dom";
import Header from "./Header";
const Root = () => {
return (
<>
<Header />
<main>
<Outlet />
</main>
</>
);
};
export default Root;
RequireAuthLayout.jsx:
import React from "react";
import { useLocation, Navigate, Outlet } from "react-router-dom";
import { useSelector } from "react-redux";
import { selectCurrentToken } from ".././features/auth/authSlice";
const RequireAuthLayout = () => {
const token = useSelector(selectCurrentToken);
const location = useLocation();
return token ? (
<Outlet />
) : (
<Navigate to={"/login"} state={{ from: location }} replace />
);
};
export default RequireAuthLayout;
PersistLogin.jsx:
import React, { useEffect } from "react";
import { Outlet } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { useRefreshMutation } from "../features/api/authApiSlice";
import { selectCurrentToken, setCredentials } from "../features/auth/authSlice";
import Loading from "../components/Loading";
const PersistLogin = () => {
const [refresh, { isLoading, isError }] = useRefreshMutation();
const dispatch = useDispatch();
const token = useSelector(selectCurrentToken);
let content;
useEffect(() => {
const getAccessToken = async () => {
try {
const result = await refresh();
dispatch(setCredentials(result.data));
} catch (error) {
// console.log(error);
}
};
!token && getAccessToken();
}, []);
if (isLoading) {
content = <Loading />;
} else if (isError) {
content = <p>Bir hata oluştu, tekrar giriş yapınız!</p>;
} else {
<Outlet />;
}
return content;
};
export default PersistLogin;
PersistLogin is just sending a request to the endpoint to check if there is a cookie. If there is and valid it sets the token in the redux store. But unfourtunately protected routes are not rendering. I mean there is no error and anything but they are not rendering. The token is okey and everything but stil..
Please help me..
The PersistLogin
component appears to not be rendering an Outlet
component for the nested routes to render their content into. <Outlet />
should be returned.
const PersistLogin = () => {
const [refresh, { isLoading, isError }] = useRefreshMutation();
const dispatch = useDispatch();
const token = useSelector(selectCurrentToken);
let content;
useEffect(() => {
const getAccessToken = async () => {
try {
const result = await refresh();
dispatch(setCredentials(result.data));
} catch (error) {
// console.log(error);
}
};
!token && getAccessToken();
}, []);
if (isLoading) {
content = <Loading />;
} else if (isError) {
content = <p>Bir hata oluştu, tekrar giriş yapınız!</p>;
} else {
content = <Outlet />; // <-- set content
}
return content;
};
or
const PersistLogin = () => {
const [refresh, { isLoading, isError }] = useRefreshMutation();
const dispatch = useDispatch();
const token = useSelector(selectCurrentToken);
let content <Outlet />; // <-- set as "default" content;
useEffect(() => {
const getAccessToken = async () => {
try {
const result = await refresh();
dispatch(setCredentials(result.data));
} catch (error) {
// console.log(error);
}
};
!token && getAccessToken();
}, []);
if (isLoading) {
content = <Loading />;
} else if (isError) {
content = <p>Bir hata oluştu, tekrar giriş yapınız!</p>;
}
return content;
};
or
const PersistLogin = () => {
const [refresh, { isLoading, isError }] = useRefreshMutation();
const dispatch = useDispatch();
const token = useSelector(selectCurrentToken);
useEffect(() => {
const getAccessToken = async () => {
try {
const result = await refresh();
dispatch(setCredentials(result.data));
} catch (error) {
// console.log(error);
}
};
!token && getAccessToken();
}, []);
if (isLoading) {
return <Loading />;
}
if (isError) {
return <p>Bir hata oluştu, tekrar giriş yapınız!</p>;
}
return <Outlet />;
};