如何使此代码与 react-router v6 兼容
Posted
技术标签:
【中文标题】如何使此代码与 react-router v6 兼容【英文标题】:How to make this code compatible for react-router v6 【发布时间】:2022-01-22 21:45:42 【问题描述】:在 ProtectedRoute.js 中我编写了代码:
const ProtectedRoute = ( component: Component, ...rest ) =>
const loading, isAuthenticated, user = useSelector((state) => state.user);
return (
<Fragment>
!loading && (
<Routes>
<Route
...rest
render=(props) =>
if (!isAuthenticated)
return <Navigate to="/login" />;
return <Component ...props />;
/>
</Routes>
)
</Fragment>
);
;
export default ProtectedRoute;
在 App.js 中我写成:
function App()
const isAuthenticated, user = useSelector((state) => state.user);
useEffect(() =>
WebFont.load(
google: families: ["Roboto", "Droid Sans", "Chilanka"] ,
);
store.dispatch(loadUser());
, []);
return (
<Router>
<Header />
isAuthenticated && <UserOptions user=user />
<Routes>
<Route exact path="/" element=<Home /> />
<Route exact path="/product/:id" element=<ProductDetails /> />
<Route exact path="/products" element=<Products /> />
<Route path="/products/:keyword" element=<Products /> />
<Route exact path="/search" element=<Search /> />
<Route exact path="/login" element=<Authenticate /> />
<ProtectedRoute exact path="/account" element=<Profile /> />
</Routes>
<Footer />
</Router>
);
export default App;
错误提示:[ProtectedRoute] 不是 Route 组件。 Routes 的所有子组件必须是 Route 或
是不是少了什么!谢谢
【问题讨论】:
【参考方案1】:在react-router-dom
中不再使用自定义路由组件。 Routes
组件只能有 Route
和 React.Fragment
组件作为子组件,Route
组件只能有 Routes
或其他 Route
组件作为父组件。
相反,包装器组件处理业务逻辑,并为嵌套的Route
组件呈现children
属性或Outlet
,或为重定向呈现Navigate
。
渲染children
const ProtectedRoute = ( children ) =>
const loading, isAuthenticated, user = useSelector((state) => state.user);
if (loading) return null;
return isAuthenticated
? children
: <Navigate to="/login" replace />;
;
...
<Route
path="/account"
element=(
<ProtectedRoute>
<Profile />
</ProtectedRoute>
)
/>
渲染Outlet
import Outlet from 'react-router-dom';
const ProtectedRoute = () =>
const loading, isAuthenticated, user = useSelector((state) => state.user);
if (loading) return null;
return isAuthenticated
? <Outlet />
: <Navigate to="/login" replace />;
;
...
<Route path="/account" element=<ProtectedRoute />>
<Route path="/account" element=<Profile /> />
</Route>
使用Outlet
的好处是您可以使用单个身份验证包装器组件并将任意数量的嵌套Route
子级渲染到其中,而使用children
方法您无法渲染嵌套路由,除非您将它们包装在Routes
组件。
【讨论】:
每次刷新页面时它都会推送到主页。我可以添加哪些更改,以便在刷新页面时它保持在同一页面上?? @MayankPandey 通常,您使用加载或“挂起”状态不提交渲染路由组件或重定向,直到应用程序确定任何身份验证状态。重新加载页面/应用时loading
和isAuthenticated
的值是多少?
如果用户已登录(isAuthenticated),它会将页面推送到主页并将加载设置为 false。
@MayankPandey 什么正在导航到您的主页"/"
?
已认证【参考方案2】:
如何翻转逻辑并像这样检查 ProtectedRoute 中的所有内容?
const ProtectedRoute = () =>
const loading, isAuthenticated, user = useSelector((state) => state.user);
if (loading) return null;
if (!isAuthenticated)
return <Navigate to="/login" />;
return <Profile user=user andWhateverElse=true />;
;
export default ProtectedRoute;
和
function App()
const isAuthenticated, user = useSelector((state) => state.user);
useEffect(() =>
WebFont.load(
google: families: ["Roboto", "Droid Sans", "Chilanka"] ,
);
store.dispatch(loadUser());
, []);
return (
<Router>
<Header />
isAuthenticated && <UserOptions user=user />
<Routes>
<Route exact path="/" element=<Home /> />
<Route exact path="/product/:id" element=<ProductDetails /> />
<Route exact path="/products" element=<Products /> />
<Route path="/products/:keyword" element=<Products /> />
<Route exact path="/search" element=<Search /> />
<Route exact path="/login" element=<Authenticate /> />
<Route exact path="/account" element=<ProtectedRoute /> />
</Routes>
<Footer />
</Router>
);
export default App;
【讨论】:
以上是关于如何使此代码与 react-router v6 兼容的主要内容,如果未能解决你的问题,请参考以下文章
React-router v6 window.scrollTo 不起作用