英文:
React Router v6.10 Protected Route problem
问题
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 unfortunately, protected routes are not rendering. I mean there is no error and anything, but they are not rendering. The token is okay and everything but still...
Please help me.
英文:
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..
答案1
得分: 0
以下是翻译好的代码部分:
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>一个错误发生,请重新登录!</p>;
} else {
content = <Outlet />; // <-- 设置内容
}
return content;
};
或
const PersistLogin = () => {
const [refresh, { isLoading, isError }] = useRefreshMutation();
const dispatch = useDispatch();
const token = useSelector(selectCurrentToken);
let content = <Outlet />; // <-- 设置为 "默认" 内容;
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>一个错误发生,请重新登录!</p>;
}
return content;
};
或
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>一个错误发生,请重新登录!</p>;
}
return <Outlet />;
};
英文:
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 />;
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论