kof*_*gna 54 javascript reactjs react-router react-router-dom
在react-router v5中我创建了这样的历史对象:
import { createBrowserHistory } from "history";
export const history = createBrowserHistory();
Run Code Online (Sandbox Code Playgroud)
然后将其传递给路由器:
import { Router, Switch, Route, Link } from "react-router-dom";
<Router history={history}>
... my routes
</Router>
Run Code Online (Sandbox Code Playgroud)
我这样做是为了有机会在组件之外使用历史记录:
// store action
logout() {
this.user = null;
history.push('/');
}
Run Code Online (Sandbox Code Playgroud)
通过这种方式,我将逻辑移至商店,并且组件尽可能保持干净。但现在,在 React Router v6 中我不能做同样的事情。我仍然可以useNavigate()在我的组件内部使用它进行导航,但我无法创建一个navigate将其使用到我的商店中的组件。还有其他选择吗?
Dre*_*ese 45
事实证明,如果您实现一个自定义路由器,以与 RRDv6 路由器相同的方式实例化历史状态,则可以复制该行为。
检查BrowserRouter实现,例如:
Run Code Online (Sandbox Code Playgroud)export function BrowserRouter({ basename, children, window }: BrowserRouterProps) { let historyRef = React.useRef<BrowserHistory>(); if (historyRef.current == null) { historyRef.current = createBrowserHistory({ window }); } let history = historyRef.current; let [state, setState] = React.useState({ action: history.action, location: history.location }); React.useLayoutEffect(() => history.listen(setState), [history]); return ( <Router basename={basename} children={children} location={state.location} navigationType={state.action} navigator={history} /> ); }
创建一个CustomRouter使用自定义history对象并管理状态的对象:
const CustomRouter = ({ history, ...props }) => {
const [state, setState] = useState({
action: history.action,
location: history.location
});
useLayoutEffect(() => history.listen(setState), [history]);
return (
<Router
{...props}
location={state.location}
navigationType={state.action}
navigator={history}
/>
);
};
Run Code Online (Sandbox Code Playgroud)
这有效地将自定义history对象代理到Router导航状态并管理导航状态。
CustomRouter从这里您可以用自定义对象替换history现有的Router导入自react-router-dom。
export default function App() {
return (
<CustomRouter history={history}>
<div className="App">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/profile" element={<Profile />} />
</Routes>
</div>
</CustomRouter>
);
}
Run Code Online (Sandbox Code Playgroud)
你的codesandbox的分支:
react-router-dom@6显示历史路由器。
<unstable_HistoryRouter>将库的实例history作为 prop。这允许您在非 React 上下文中使用该实例或作为全局变量。Run Code Online (Sandbox Code Playgroud)import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom"; import { createBrowserHistory } from "history"; const history = createBrowserHistory({ window }); ReactDOM.render( <HistoryRouter history={history}> {/* The rest of your app goes here */} </HistoryRouter>, root );
有这样一条注释:
此 API 目前带有前缀,
unstable_因为您可能会无意中向应用程序添加两个版本的history库,即添加到 package.json 中的版本和 React Router 内部使用的任何版本。如果您的工具允许,建议不要添加history为直接依赖项,而是依赖react-router包中的嵌套依赖项。一旦我们有了检测不匹配版本的机制,该 API 将删除其unstable_前缀。
如果您使用 RRDv6.4+ 并且不使用数据路由器,那么好消息是至少仍通过 RRDv6.7.0unstable_HistoryRouter导出。您可以在此处跟踪存储库中提交的问题。
如果您使用数据路由器,那么新的“不稳定”方法是navigate直接使用路由器对象的附加函数。
例子:
export function BrowserRouter({
basename,
children,
window
}: BrowserRouterProps) {
let historyRef = React.useRef<BrowserHistory>();
if (historyRef.current == null) {
historyRef.current = createBrowserHistory({ window });
}
let history = historyRef.current;
let [state, setState] = React.useState({
action: history.action,
location: history.location
});
React.useLayoutEffect(() => history.listen(setState), [history]);
return (
<Router
basename={basename}
children={children}
location={state.location}
navigationType={state.action}
navigator={history}
/>
);
}
Run Code Online (Sandbox Code Playgroud)
小智 7
更简单的代码(react-router-dom@6.15.0),我喜欢这样
1-创建一个浏览器路由器对象router.tsx:
import { createBrowserRouter } from 'react-router-dom';
const router = createBrowserRouter([
{
path: '/',
element: <HomePage />,
},
{
path: 'page',
element: <SomePage />,
}
]);
export default router;
Run Code Online (Sandbox Code Playgroud)
2-然后在App.tsx(或您想要使用路由器的地方):
import { RouterProvider } from 'react-router-dom';
import router from '@/router';
function App() {
return (
<main>
<RouterProvider router={router} />
</main>
);
}
export default App;
Run Code Online (Sandbox Code Playgroud)
3-现在从组件外部导航
import router from '@/router';
...
router.navigate('/path-to-go');
Run Code Online (Sandbox Code Playgroud)
已接受答案的 TypeScript 解决方案
历史对象:
import { createBrowserHistory } from "history";
const customHistory = createBrowserHistory();
export default customHistory;
Run Code Online (Sandbox Code Playgroud)
BrowserRouterProps 是一种反应路由器类型。
Run Code Online (Sandbox Code Playgroud)export interface BrowserRouterProps { basename?: string; children?: React.ReactNode; window?: Window; }
自定义路由器:
import { useLayoutEffect, useState } from "react";
import { BrowserRouterProps, Router } from "react-router-dom";
import { BrowserHistory } from "history";
import customHistory from "./history";
interface Props extends BrowserRouterProps {
history: BrowserHistory;
}
export const CustomRouter = ({ basename, history, children }: Props) => {
const [state, setState] = useState({
action: history.action,
location: history.location,
});
useLayoutEffect(() => history.listen(setState), [history]);
return (
<Router
navigator={customHistory}
location={state.location}
navigationType={state.action}
children={children}
basename={basename}
/>
);
};
Run Code Online (Sandbox Code Playgroud)
使用 CustomRouter 代替 BrowserRouter
ReactDOM.render(
<React.StrictMode>
<CustomRouter history={customHistory}>
<App />
</CustomRouter>
</React.StrictMode>,
document.getElementById("root")
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
57775 次 |
| 最近记录: |