如何使用react-router重新加载页面?

83
我在这个文件中看到(https://github.com/ReactTraining/react-router/blob/v0.13.3/modules/createRouter.js)有一个刷新函数,但我不知道如何调用它。我对react-router比较陌生,之前只用过hashHistory在一些页面之间跳转。

现在我想在安装失败时使用它,让用户可以选择“重试”,我打算通过刷新正在进行安装的页面(用户当前所在的页面)来执行此操作。任何帮助将不胜感激。

这是一个在electron上运行的node应用程序,而不是web应用程序。

22个回答

113

首先,将react-router添加为依赖项

yarn add react-routernpm install react-router

然后(针对react-router v5)

import { useHistory } from 'react-router'

const history = useHistory()

// then add this to the function that is called for re-rendering
history.go(0)

这会导致您的页面自动重新渲染。

对于 react-router v6,请改用 useNavigate hook:

import { useNavigate } from 'react-router'

const navigate = useNavigate()

// refresh
navigate(0)

1
如果您在处理身份验证状态的onClick事件中删除了一个cookie,那么这将起作用。使用history.go(),我按预期注销并推送到登录屏幕。对于其他答案,我没有按预期工作。 - Lucas Reppe Welander
6
不是真正的SPA方法。我认为这个建议应该受到批评。 - Ott
1
我正在使用React和Express.js构建Web应用程序,这个建议对我非常有效。干杯! - Giovanni Pizzato
1
不适用于react-router v6(尝试过' navigate(0)')。 - Andrey

41

如果你正在使用 react-router v6

import { useNavigate } from "react-router-dom";

const navigate = useNavigate();

const refreshPage = () => {
    navigate(0);
}

1
我发现如果您是通过路由器作为注销序列的一部分进行此操作,则最好先刷新导航到主页路由,即:导航("/"); 导航(0); - bownie

27

您可以使用此功能刷新当前路由:

import createHistory from 'history/createBrowserHistory'
const history = createHistory();
history.go(0)

9
这会导致整个页面重新加载。 - Aleksey L.
如果您正在使用hooks,可以尝试类似的方法 - 这适用于来自react-router-dom的useHistory。但是,是的,需要完全重新加载页面。 - Julian

24

其实您不需要使用react-router,只需使用location.reload即可:

location.reload();

同时,你链接的那个react-router版本非常老,我认为它链接的是v1版本,而现在已经更新到了v4版本。


@Sheriff 哦,也许可以尝试另一个答案。但是你也可以尝试使用 contents.reload - Austin Greco
78
不是真正的SPA方法。我认为这个建议应该受到批评。 - Sasha Kos
3
我认为这里其他的回答,比如history.pushState(null, '/'); 更好。 - Sasha Kos
1
使用此方法会丢失任何缓存的数据(例如Apollo),而使用路由器方法则不会。 - Wil Wells
6
有时候需要采取这种方法,比如当我们部署 SPA 应用程序的新版本,并且我们希望维护模式下线组件(显示给用户)触发完整页面刷新并获取 SPA 应用程序的新版本(一旦我们关闭维护模式)。请注意,为了解决使用此代码时出现“no-restricted-globals”错误(例如使用 Create React App 时),应将其更改为“window.location.reload()”。 - shlgug
显示剩余4条评论

14

React

window.location.reload();

工作中


14
这可能会导致无限循环,请小心。 - Desarrollalab
这可能导致无限循环?请提供一些例子来加强你的说法。 - Jan
1
@Jan 如果你把这个放在 useEffect 里面,它会在组件重新加载时触发,而每次页面加载都必然会发生重新加载,这将导致页面不断加载等问题。 - tinkoh

14

我猜你正在使用react-router。 我将复制我的另一篇文章中的答案。 所以你有几种可能的方法来做到这一点,目前我最喜欢的方法是在组件属性中使用匿名函数:

<Switch>
  <Route exact path="/" component={()=><HomeContainer/>} />
  <Route exact path="/file/:itemPath/:refHash" component={()=><File/>} />
  <Route exact path="/:folderName" component ={()=><Folder/>}/>
</Switch>
如果您想使用当前的URL参数进行刷新,您需要添加额外的路由(reload),并对路由器堆栈进行微调。
reload = ()=>{
 const current = props.location.pathname;
 this.props.history.replace(`/reload`);
    setTimeout(() => {
      this.props.history.replace(current);
    });
}

<Switch>
  <Route path="/reload" component={null} key="reload" />
  <Route exact path="/" component={HomeContainer} />
  <Route exact path="/file/:itemPath/:refHash" component={File} />
  <Route exact path="/:folderName" component ={Folder}/>
</Switch>

<div onClick={this.reload}>Reload</div>

3
为什么这里需要使用setTimeout - Dawson B
1
@DawsonB 我不知道,但是没有它就不能正常工作.. 哈哈 - Newoda
@DawsonB 如果您立即重新加载页面,则更改的路由不会保留。 setTimeout 的最小值取决于浏览器,通常在 4-10 毫秒之间,因此这实际上是通过 URL 更改页面并使用最小超时重新加载页面。 "没有它就无法工作" 是因为如果没有延迟刷新,则“当前”还不是新页面。 - ATLUS

13

如果您想重新获取数据,请按以下步骤操作:

import { useLocation } from 'react-router'

const location = useLocation()

useEffect(() => {
  fetchData()
}, [location.key])

1
甜蜜的解决方案! - lloyd agola
多么小,就有多聪明。 - mabruk

10

我知道这已经有些过时了,但我在react-router的文档中找到了一个简单的解决方案。

只需将该属性放在你的Router上,每当你在一个新的路径上时,它将强制页面重新加载自己。

<Router forceRefresh={true}>

Source: https://reactrouter.com/web/api/BrowserRouter/forcerefresh-bool


哇!无需使用生成的唯一ID添加密钥等,这是最好的解决方案!Terima Kasih! - metalheadcoder
这对我很有帮助!非常感谢。我正在使用React-Router-Dom 5.2.0版本。 - The Grindfather

7
这种解决方案不会导致意外的全页面刷新,但是需要您对需要刷新的每个页面进行以下修改:
export const Page = () => {
   const location = useLocation();
   return <PageImpl key={location.key} />
}

这个想法是:创建一个包装器围绕您的页面,并使React每次更改位置键时重新创建实际页面。

现在只需再次调用history.push(/this-page-route),页面就会刷新。


1
感谢您注意到 histry.push(..) 会触发刷新。 - Joey Baruch

5

如果你想使用<Link/>重新加载某个路由,或者仅执行单一的历史记录推送,你可以像这样在<Switch/>下设置<Redirect/>路由:

<Switch>
    <Route exact path="/some-route" component={SomeRoute} />
    <Redirect exact from="/some-route/reload" to="/some-route" />
</Switch>

然后是 <Link to="/some-route/reload" /> 或者 push("/some-route/reload")


有趣的方法,对我的使用情况很有效。谢谢! - Wasim Abuzaher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接