好吧,因为我不知道你是否想要嵌套路由,所以我想我会在这里帮助你一点。由于您没有发布与 redux 相关的任何内容,因此我将其省略了。这是一个包含嵌套路由和普通路由 Codesandbox 的工作代码框。
在下面的示例中,我只是使用了一个工作示例,因此我只是使用状态来控制令牌。您可以稍后将其转入您的const token = window.localStorage.getItem('token');,但我想要一个您可以轻松遵循的示例。而且由于我不知道您的代码的范围,我认为只给您一个工作示例会更容易。
这是一个没有嵌套路由的普通示例:
import React, { useState } from "react";
import {
BrowserRouter,
Routes,
Route,
Link,
Navigate,
useLocation,
useNavigate
} from "react-router-dom";
const Component: React.FC<{ title: string }> = ({ title }) => <h1>{title}</h1>;
const PrivateRoute: React.FC<{ token: boolean }> = ({ token, children }) => {
const location = useLocation();
return token ? (
<>{children}</>
) : (
<Navigate to="/login" state={{ from: location }} />
);
};
const Login: React.FC<{ setToken: any }> = ({ setToken }) => {
const navigate = useNavigate();
const location: any = useLocation();
let from = location.state?.from?.pathname || "/";
const handleLogin = () => {
setToken(true);
navigate(from, { replace: true });
};
return <button onClick={handleLogin}>Login</button>;
};
export default function App() {
const [token, setToken] = useState<boolean>(false);
return (
<div className="App">
<BrowserRouter>
<Link to="/">Home</Link> | <Link to="/dashboard">Dashboard</Link>
<Routes>
<Route path="/" element={<Component title="Home" />} />
<Route path="/login" element={<Login setToken={setToken} />} />
<Route path="/dashboard" element={
<PrivateRoute token={token}>
<Component title="Dashboard"/>
</PrivateRoute>
} />
</Routes>
</BrowserRouter>
</div>
);
}
所以你可以看到在私有路由组件中我们正在检查令牌。如果有一个令牌,那么我们将只渲染孩子,否则我们将导航到登录页面。在登录页面中,我们提供登录功能,然后我们将获取位置状态,一旦登录,我们将自动将用户重定向到他们尝试访问的页面。
这是一个嵌套路由示例:
import React, { useState } from "react";
import {
BrowserRouter,
Routes,
Route,
Link,
Navigate,
Outlet,
useLocation,
useNavigate
} from "react-router-dom";
const Component: React.FC<{ title: string }> = ({ title }) => <h1>{title}</h1>;
const PrivateRoute: React.FC<{ token: boolean }> = ({ token, children }) => {
const location = useLocation();
return token ? (
<>{children}</>
) : (
<Navigate to="/dashboard/login" state={{ from: location }} />
);
};
const Login: React.FC<{ setToken: any }> = ({ setToken }) => {
const navigate = useNavigate();
const location: any = useLocation();
let from = location.state?.from?.pathname || "/";
const handleLogin = () => {
setToken(true);
navigate(from, { replace: true });
};
return <button onClick={handleLogin}>Login</button>;
};
const Dashboard: React.FC = () => {
return (
<div>
<Outlet />
</div>
);
};
export default function App() {
const [token, setToken] = useState<boolean>(false);
return (
<div className="App">
<BrowserRouter>
<Link to="/">Home</Link> | <Link to="/dashboard">Dashboard</Link>
<Routes>
<Route path="/" element={<Component title="Home" />} />
<Route path="/dashboard" element={<Dashboard />}>
<Route
path="/dashboard"
element={
<PrivateRoute token={token}>
<Component title="Dashboard" />
</PrivateRoute>
}
/>
<Route
path="/dashboard/login"
element={<Login setToken={setToken} />}
/>
</Route>
</Routes>
</BrowserRouter>
</div>
);
}
在这里您可以看到我们在仪表板组件中使用插座作为占位符。这让反应路由器知道我们想要渲染一些嵌套路由。如果你想将你的路由嵌套在仪表板组件中,那么你不需要使用出口组件,你可以这样做:
const Dashboard: React.FC<{ token: boolean; setToken: any }> = ({
token,
setToken
}) => {
return (
<div>
<Routes>
<Route
path="/"
element={
<PrivateRoute token={token}>
<Component title="Dashboard" />
</PrivateRoute>
}
/>
<Route path="/login" element={<Login setToken={setToken} />} />
</Routes>
</div>
);
};
export default function App() {
const [token, setToken] = useState<boolean>(false);
return (
<div className="App">
<BrowserRouter>
<Link to="/">Home</Link> | <Link to="/dashboard">Dashboard</Link>
<Routes>
<Route path="/" element={<Component title="Home" />} />
<Route
path="/dashboard/*"
element={ <Dashboard token={token} setToken={setToken} /> } />
</Routes>
</BrowserRouter>
</div>
);
}