我用 Astro、React 和 RRDv6 构建了这个简单的混合 SPA
路由树:
˫ localhost/ ------------------(公共页面)
˫ localhost/login ------------(管理员登录页面)
˪ localhost/admin/home ---(管理仪表板页面)
当我成功登录并重定向到管理仪表板页面时,没有错误或任何警告出现。我尝试刷新页面来模拟刷新仪表板以通过API从数据库中获取最新数据。相反,我的控制台日志中出现此错误,并且我的页面呈现为空白。
未捕获错误:
只能在以下情况下使用:useNavigate()
组件。<Router>
我是否错过了 RRDv6 概念,或者错过了一些重要的东西?
env: node 16.13.0, npm 8.3.0
deps: @astrojs/react 2.0.2, astro 2.0.16, react 18.2.0, react-router-dom 6.11.1
script: dev = astro dev
cmd: npm run dev
路线:
export default function Admin() {
const [cookie, setCookie, removeCookie] = useCookies(['token']);
const PrivateRoute = () => {
const location = useLocation()
const isAuthenticated = () => {
return cookie.token !== null && cookie.token !== undefined;
};
return isAuthenticated()
? <Outlet />
: <Navigate to="/admin" replace state={{ from: location }} />;
};
return (
<BrowserRouter>
<Routes>
<Route path="/login" element={<AdminLogin />} />
<Route path="/admin" element={<PrivateRoute />}>
<Route path="home" element={<AdminHome />} />
</Route>
</Routes>
</BrowserRouter>
);
}
管理仪表板:
export default function AdminHome() {
const [cookie, setCookie, removeCookie] = useCookies(['token']);
const [doLogout, setDoLogout] = useState(false)
const navigate= useNavigate()
useEffect(() => {
if (doLogout) {
removeCookie('token', { sameSite: 'none', secure: true })
navigate('/login')
}
}, [doLogout])
return (
<div>
<AdminAppbar cookie={cookie} logout={setDoLogout} />
<AdminBlog/>
</div>
);
}
我在代码中看到的唯一问题是:
PrivateRoute
组件在另一个 React 组件中声明。每次父组件渲染时,都会创建 PrivateRoute
的新“实例”,并且 that 组件的整个 ReactTree 会被拆除并安装新的“实例”。 React 组件通常应该单独声明。
isAuthenticated
评估为 false 时,
受保护的路由将重定向到自身。这可能会创建渲染循环,这就是页面为空白的原因。您正在保护的路由不应重定向到其他受保护的路由。更新
PrivateRoute
以重定向到身份验证路由。
const PrivateRoute = () => {
const location = useLocation();
const [cookie, setCookie, removeCookie] = useCookies(['token']);
const isAuthenticated = cookie.token !== null && cookie.token !== undefined;
return isAuthenticated
? <Outlet />
: (
<Navigate
to="/login" // <-- redirect to non-protected route
replace
state={{ from: location }}
/>
);
};
export default function Admin() {
return (
<BrowserRouter>
<Routes>
<Route path="/login" element={<AdminLogin />} />
<Route path="/admin" element={<PrivateRoute />}>
<Route path="home" element={<AdminHome />} />
</Route>
</Routes>
</BrowserRouter>
);
}