这个问题在@ionic/react 7.4和7.5两个版本中都存在。
我有两个简单的路由定义如下:
<IonRouterOutlet id="main">
...
<Route path="/campaigns" exact={true} render={props => <CampaignList {...props} />} />
<Route path="/campaign/:title" exact={true} render={props => <CampaignDetail {...props} />} />
...
</IonRouterOutlet>
第一个路由显示一个列表,每个列表项都定义了一个onClick
方法,该方法调用一个名为getCampaignDetail
的方法,该方法导航到第二个路由,如下所示:
const getCampaignDetail = (title:string) => {
navigate(`/campaign/${title}`, 'root');
}
当我加载应用程序时,它默认为/campaigns
该视图加载没有问题,并显示列表
如果我点击一个列表项,它会正确导航到/campaign/:title
然后使用浏览器的后退按钮加载/campaigns
/campaigns
视图加载没有问题
然后,在点击不同的列表项时,我可以说我绝对肯定它试图加载不同的:title
,因为:
1.我在控制台记录值之前,它导航,并看到该值显然是不同
1.浏览器中的URL清楚地显示好像参数:title
是不同的,并且从我上次访问此路由时起已经更改
尽管如此,当我在CampaignDetail
组件中控制台记录:title
时(useIonViewDidEnter
方法中的/campaign/:title
加载的组件),:title
正在打印,就好像它的值从我第一次访问/campaign:title
时没有改变一样。
在我的CampaignDetail
组件中,我尝试了两种方法之一检索参数,第一种是直接从props中检索:
type MatchParams = {
title: string;
};
const CampaignDetail: React.FC<RouteComponentProps> = (props) => {
const { title } = props.match.params as MatchParams;
...
使用useParams
钩子:
const CampaignDetail: React.FC<RouteComponentProps> = (props) => {
const { title } = useParams<{ title: string; }>();
...
在useIonViewDidEnter
方法中,我尝试控制台日志:title
useIonViewDidEnter(() => {
console.log("PARAMETER:", title);
});
此行为仅在使用浏览器的后退按钮后发生。
为什么在使用浏览器的后退按钮后,参数不能反映后续访问的正确值?
在阅读文档并对此问题进行其他研究后,为了解决此问题,我尝试向路由添加key
作为解决方案,如下所示:
<Route path="/campaign/:title" exact={true} render={props => <CampaignDetail key={props.match.params.title} {...props} />} />
然而,这会导致甚至更糟糕的行为,因为在使用浏览器的后退按钮之后,对/campaign:title
的后续访问会导致useIonViewDidEnter
方法执行多次,并且每次执行时,我都会看到:title
的行为就像是在我每次打印到控制台时访问的两个值之间切换一样。首先,我看到的值是我第一次访问时的值,然后是新的值,然后它打印第一个值,大约3-4次,最后才停止。
看到这种行为说明了很多问题,因为使用浏览器的后退按钮显然会导致与路由参数有关的奇怪行为。
我能做些什么来解决这个问题?
更新:
我注意到,当我在路由/campaign/:title
上点击浏览器的后退按钮时,组件CampaignDetail
中的useIonViewDidEnter
函数再次触发,而它不应该考虑到我已经离开了该路由并导航回/campaigns
。
其他异常行为:
根据@Aafaq的建议,我检查location
作为故障排除的一种手段,我这样做了,结果发现了奇怪的行为。
如果我将useIonViewDidEnter
方法全部注解掉,并使用下面的useEffect
钩子和location
来检查路径更改,如下所示:
const campaignDetailTitleRef = useRef('');
useEffect(() => {
const parts = location.pathname.split('/');
const getPathTitle = parts[2];
if (getPathTitle && getPathTitle !== campaignDetailTitleRef.current) {
campaignDetailTitleRef.current = getPathTitle;
console.log("PARAMETER:", getPathTitle);
}
},[location.pathname]);
当应用程序加载启动路由/campaigns
,然后我点击一个列表项,我看到console.log("PARAMETER:", getPathTitle);
只打印一次,正如预期的那样,当/campaign/:title
加载时,它显示正确的值,因为它是从location
解析的。
然后我点击浏览器的后退按钮,随后,我点击了一个不同的列表项,虽然getPathTitle
的值实际上是正确的打印现在已经从location
而不是params检索到该值,我看到console.log("PARAMETER:", getPathTitle);
打印两次这告诉我,要么campaignDetailTitleRef.current = getPathTitle
在钩子第一次运行后没有设置,要么组件加载了两次,很难判断是哪种情况。很难排除正在发生的故障。
像页面导航这样简单的事情,在url中只需要一个动态参数,应该不会那么困难。这使得Ionic React在浏览器中毫无价值。
2条答案
按热度按时间wj8zmpe11#
我建议您使用react-router-dom中的useLocation钩子来记录当前位置及其状态,以便进行调试。这可以帮助您识别与路由更改相关的任何意外行为。示例如下:
ubbxdtey2#
看起来,用
<Switch>
组件 Package 路由可以确保一次只匹配一个路由,并可以防止我所描述的行为。