英文:
Refreshing the page causes the page to be rendered blank and navigate() error is thrown
问题
I have this simple hybrid SPA build with Astro, React, and RRDv6
路由树:
- localhost/ ------------------(公共页面)
- localhost/login ------------(管理员登录页面)
- localhost/admin/home ---(管理员仪表板页面)
当我成功登录并重定向到管理员仪表板页面时,没有任何错误或警告。我尝试刷新页面以模拟刷新仪表板以通过API从数据库中获取最新数据。相反,我在控制台日志中遇到了以下错误,并且我的页面呈现为空白。
> 未捕获的错误:useNavigate()
只能在 <Router>
组件的上下文中使用。
我是否遗漏了RRDv6的概念,或者遗漏了重要的内容?
环境:node 16.13.0,npm 8.3.0
依赖:@astrojs/react 2.0.2,astro 2.0.16,react 18.2.0,react-router-dom 6.11.1
脚本:dev = astro dev
命令: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>
);
}
英文:
I have this simple hybrid SPA build with Astro, React, and RRDv6
Route tree:
˫ localhost/ ------------------(public page)
˫ localhost/login ------------(admin login page)
˪ localhost/admin/home ---(admin dashboard page)
When I have successfully logged in and redirected to admin dashboard page, no error or any warning is present. I tried to refresh the page to simulate refreshing dashboard to fetch latest data from database through API. Instead I am having this error in my console log and my page is rendered blank.
> Uncaught Error: useNavigate()
may be used only in the context of a
> <Router>
component.
Am I missing the RRDv6 concept, or missing something that is important?
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
Routes:
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>
);
}
Admin Dashboard:
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>
);
}
答案1
得分: 0
The only issues I see in the code are:
PrivateRoute
组件声明在另一个 React 组件内部。每当父组件重新渲染时,都会创建一个新的 "PrivateRoute" 实例,而该组件的整个 React 树将被销毁,然后新的 "PrivateRoute" 实例将被挂载。通常情况下,应该单独声明 React 组件。- 当
isAuthenticated
评估为假值时,受保护的路由将重定向到自身。这可能会创建一个渲染循环,这就是页面为空的原因。您要保护的路由不应该重定向到其他受保护的路由。
请更新 PrivateRoute
以重定向到认证路由。
英文:
The only issues I see in the code are:
-
The
PrivateRoute
component is declared inside another React component. Each time the parent component renders, a new "instance" ofPrivateRoute
is created and that component's entire ReactTree is torn down and the new "instance" mounted. React components generally should be declared on their own. -
The protected route is redirecting to itself when the
isAuthenticated
evaluates falsey. This is likely creating a render loop which is why the page is blank. Routes you are protecting should not redirect to other protected routes.Update
PrivateRoute
to redirect to the authentication route.
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>
);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论