【发布时间】:2021-08-16 14:26:10
【问题描述】:
在我的项目中,我使用 React Router DOM 5.2.0。由于项目需要,我必须使用带有自定义历史记录的<Router />。事情是这样的:
history.js
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
export default history;
useRouter.js
import {
useParams,
useRouteMatch,
} from 'react-router-dom';
import { useMemo } from 'react';
import history from './history';
import urlQueriesService from './urlQueriesService';
const useRouter = () => {
const params = useParams();
const match = useRouteMatch();
const { location } = history;
return useMemo(() => ({
push: history.push,
replace: history.replace,
pathname: location?.pathname,
query: {
...urlQueriesService.parse(location?.search),
...params,
},
match,
location,
history,
}), [params, match, location, history]);
};
export default useRouter;
AppRoutes.jsx
import React from 'react';
import {
Route,
Switch,
} from 'react-router-dom';
import useRouter from './useRouter';
import TestPage from './TestPage';
import TestComponent from './TestComponent';
const AppRoutes = () => {
const { location } = useRouter();
return (
<Switch location={location}>
<Route exact path="/page-1" component={Page1} />
<Route exact path="/page-2" component={Page2} />
</Switch>
);
};
export default AppRoutes;
App.jsx
import history from './history';
<Router history={history}>
<AppRoutes />
</Router>
这是基本设置。 Page1 和 Page2 是交叉链接组件,如下所示:
import React from 'react';
import { Link } from 'react-router-dom';
import useRouter from './useRouter';
const Page1 = () => {
const { location } = useRouter();
return (
<div>
<h1>Test</h1>
<div>
<Link to={{ pathname: '/page-2', state: { prevUrl: location.pathname }}}>Stateful component</Link>
</div>
</div>
);
};
export default Page1;
这里的关键部分是Link 组件,它具有to 以对象为值的prop。在这个对象中我定义了state: { prevUrl: location.pathname },但是当我尝试在Page2 中访问它时,这个state 始终是null。这里有趣的是,如果我将<Router /> 更改为BrowserRouter 并从Switch 中删除自定义location - 一切都会很好,这意味着<Link /> 确实会传播状态。然而,就我而言,history 似乎根本没有处理状态。
系统:
- Mac OS 11.4 Big Sur
- 节点 12.16.2
- NPM 6.14.11
- 反应 16.13.1
- react-router-dom 5.2.0
【问题讨论】:
-
为什么不在
useRouter自定义挂钩中使用useLocation挂钩?你为什么要在Switch组件上使用不同的 位置?您可以毫无问题地将Router与createBrowserHistoryhistory对象一起使用,我认为这是Switch上使用的奇怪location对象为您搞砸了。 -
似乎
Switch需要知道location对象用于正确处理组件更新。如果我删除一个 - 它不会呈现新组件。在useRouter中,我使用我创建的history对象中的location来提供给Router,这就是我不使用useLocation的原因,因为它会从不同的对象返回我的位置。我创建了一个沙箱,以便更轻松地点击codesandbox.io/embed/…
标签: reactjs react-router react-router-dom history.js react-router-v5