在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或<反应片段>。
是不是少了什么东西!谢谢
在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
组件中,否则无法呈现嵌套路由。
像这样翻转逻辑并检查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;