【发布时间】:2021-11-10 01:18:37
【问题描述】:
这经常出现,但似乎没有解决方案有效,我觉得我已经用尽了我能想到的每一个选项,所以我转向这里,相信这可能是一个稍微不同的场景,而不是重复。如果有可行的现有解决方案,我很高兴得到其他展示。
在我上一个 create-react-app 项目中,使用 Router 和 useHistory 渲染新页面没有问题。使用完全相同的设置,我遇到了history.push(url) 更改地址栏中的 url 但页面没有重新呈现的问题。
我正在使用:
- 反应 v17.0.2
- react-router-dom v5.3.0
- 历史 v5.0.1(也尝试过 在 v4.10.1 上)
App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import { Page } from './stories/Page';
import './App.css';
function App() {
return (
<Router>
<Switch>
<Route exact path="/">
<Page homepage={true} />
</Route>
<Route path="/project/([a-zA-Z0-9]+)/([a-z\-0-9]+)/([a-z\-0-9]+)/" render={urlprops =>
<Page projectID={urlprops.match.params[0]} homepage={false} />
} />
<Route path="/project/([a-zA-Z0-9]+)/([a-z\-0-9]+)/" render={urlprops =>
<Page projectID={urlprops.match.params[0]} homepage={false} />
} />
</Switch>
</Router>
);
}
export default App;
component-page.js
import React, { useEffect, useState, useCallback } from 'react';
import PropTypes from 'prop-types';
import { useHistory } from 'react-router-dom';
import './menuitem.css';
export const Component = ({ url, ...props }) => {
let history = useHistory();
function handleItemClick(e) {
history.push(url); // <- calls fine, tested with logging to console
}
...
我看到旧的解决方案建议通过 Router 传递历史道具,但在我的上一个应用程序中,我能够使用上面的设置,并且任何级别嵌套的子组件都可以调用 useHistory 如果像上面的 component-page.js 那样设置,则挂钩并使用 push。因此,我没有展示 App.js 和 component-page.js 之间的组件,因为我认为这应该与 useHistory 正常运行无关。
可能相关:
- 如果我在地址栏中输入 URL 并回车,Router 会呈现正确的组件,提示 Router 和 Switch 可以正常工作一个新加载的页面。
- 我已将 React 开发工具设置为闪烁
组件重新渲染时。在
history.push(url)被全部调用之后 组件闪烁,但没有重新渲染(至少在视觉上)。 - 将历史记录降级到 4.10.1 似乎解决了很多问题 其他人对此问题的最新报告。我没有这样的运气。显然,react-router-dom v5+ 存在/存在一个错误,这意味着 history.push 不适用于 history v5+。
- 我还在 Page 组件中放置了一个简单的按钮组件,该组件向 history.push("string url here") 发出了相同问题的请求。它调用,地址栏更改,页面不会重新呈现。在我看来,这排除了它是某种嵌套问题,无论如何我都不相信它。
更新
在调用history.push('url string') 后在控制台中检查历史记录会在 location 属性下显示以下内容。这看起来像预期的那样(我只希望路径名与我试图指向的 url 匹配)。
{
"pathname": "url string",
"search": "",
"hash": "",
"key": "ctks7v"
}
更新 2
可能的进展。在我的 Page 组件中,我在挂钩中调用 fetch 以捕获任何更新,如下所示:
useEffect(() => {
apiFetchProject(projectID);
}, []);
我现在想知道这是否是我的问题?这个钩子没有将 url 视为需要触发 apiFetchProject(projectID) 的更改。我这么说的原因是控制台调用确认在我的 history.push 之后没有在此处调用此钩子,但是对 Page 组件的控制台调用 正在发生。我已经尝试在 props.location 中进行任何更改来调用该钩子,但这每次都会返回为未定义,这意味着不会调用该钩子。
更新 3
如果在 Page 上,我使用 import { useLocation } from "react-router-dom"; 和 let location = useLocation(); 并让钩子查找 location 的变化,Page 现在可以成功调用 @987654334 @ 在history.push 呼叫之后。但是也必须这样做似乎有些不对劲?我觉得我会将其视为标准说明。
我必须将它添加到每个组件中才能看到重新渲染的任何内容。 Page 中的 fetch 存储为状态,并作为 prop 传递给子组件。此状态的更改应自动重新呈现所有传递给它的子组件,就像加载页面时发生的那样。
【问题讨论】:
-
前段时间我也遇到过类似的问题,我想我是通过“欺骗”响应重新渲染来解决的,方法是使用时间戳给它一个新的键。
标签: javascript reactjs react-router-dom