强制React-Router <link />加载页面,即使我们已经在该页面上

时间:2016-08-08 22:36:07

标签: react-router

有没有办法强制React-Router <Link>从路径加载页面,即使当前位置已经是该页面?我似乎无法在react-router文档中找到任何提及。

我们在“申请”路线上有一个页面,用于加载带有英雄形象,一些解释性文字等的着陆页,以及一个“申请此程序”按钮,该按钮交换作为应用程序的内容形成。这一切都发生在相同的“应用”路线上,因为如果没有首先点击着陆页,用户就无法直接导航到此表单。

然而,当他们打开这个表单时,他们再次单击导航菜单中的apply链接,整个页面应该像第一次安装时那样重新加载,让他们“回来”(但实际上,向前)到再次登陆页面。

相反,单击<Link>不会执行任何操作,因为react-router看到我们已经在“apply”页面上,因此不会卸载当前页面然后安装另一个页面。

在安装所请求的页面之前,有没有办法强制卸载当前页面,即使页面用户应该已经打开了? (例如通过<Link>属性?)

15 个答案:

答案 0 :(得分:8)

不是一个好的解决方案,因为它强制完整页面刷新并抛出错误,但您可以使用onClick处理程序调用forceUpdate(),如:

<Link onClick={this.forceUpdate} to={'/the-page'}>
    Click Me
</Link>

我只能说是有效的。我自己也陷入了类似的问题,并希望别人有更好的答案!

React router Link not causing component to update within nested routes

答案 1 :(得分:6)

在“路由”组件中,指定一个随机密钥。

<Route path={YOURPATH} render={(props) => <YourComp {...props} keyProp={someValue} key={randomGen()}/>} />

当反应看到不同的键时,它们将触发重新渲染。

答案 2 :(得分:4)

我过去常常解决的一个问题就是将state属性传递给像<Link to={{pathname: "/page", state: "desiredState"}}>Page</Link>这样的链接。然后我可以在目标组件(例如<Page />componentWillReceiveProps中检查这一点,如下所示:

componentWillReceiveProps(nextProps){
  if (nextProps.location.state === 'desiredState') {
    // do stuffs
  }
}

这可以避免整页重新加载。 与我的回答here

相关联

答案 3 :(得分:3)

这可能是一个普遍的问题,我一直在寻找下一次在我的工具表中提供一个不错的解决方案。 React-Router 提供了一些机制来知道用户何时尝试访问任何页面,甚至是已经访问过的页面。

读取cld.mixed_C_L <- structure(list(managem = structure(c(1L, 3L, 2L), .Label = c("CH", + "CHF", "WTH"), class = "factor"), response = c(2.46142878854869, + 2.47526369032351, 3.25797765207699), SE = c(0.111893590886356, + 0.112522508873481, 0.148103743733873), df = c(5.22163854368496, + 5.22163854368496, 5.22163854368496), lower.CL = c(2.10382917999276, + 2.11565412905959, 2.78465437801484), upper.CL = c(2.87981160196529, + 2.89599809934785, 3.81175432945472), .group = c("a", "a", "b" + )), row.names = c(1L, 3L, 2L), class = "data.frame") 哈希是一种完美的方法,因为每次用户尝试在任何页面之间导航时,它都会更改。

plot.mixed.lme<-ggplot(cld.mixed_C_L,aes(x = managem,y=response,color= managem, label=.group))+ 
        theme_bw()+
        geom_point(shape  = 15, size   = 4) +
        geom_errorbar(aes(ymin  =  lower.CL,ymax  =  upper.CL),width =  0.2,size  =  0.7)+ 
        theme(aspect.ratio = 2/1) + 
#### following lines adds legend inside the boxplot:
        theme(legend.justification=c(1,0), legend.position=c(1,0),
        legend.direction="vertical",
        legend.box="vertical",
        legend.box.just = c("top"), 
        legend.background = element_rect(fill=alpha('white', 0.4)))+
        #removes legend:
        guides(fill = FALSE, color= FALSE) +
#### remove axis labels:
        theme(plot.title = element_blank(), axis.title.x = element_blank(), axis.title.y = element_blank()) +
#### move significance letters:
        geom_text(nudge_x = c(0.3, 0.3, 0.3),
                  nudge_y = c(0, 0,0),
                  color   = "black") +
#### set colours of the boxes:
        scale_color_manual(values = c("#333333", "#333333", "#333333"))+
        annotation_custom(my_grob)
### print three plots as example: 


plot.mixed.lme
plot.mixed.lme
plot.mixed.lme

设置新状态后,将调用render方法。在示例中,我将状态设置为默认值。

参考:A location object is never mutated so you can use it in the lifecycle hooks to determine when navigation happens

答案 4 :(得分:1)

在React-router-dom v5.1.2中,我的工作方式与@ peiti-li的回答稍有不同,因为在我的情况下,尝试解决方案后,我的页面陷入了无限渲染循环中。

以下是我的工作。

<Route
  path="/mypath"
  render={(props) => <MyComponent key={props.location.key} />}
/>

每次路线更改时,即使用户已经在同一条路线上,location.key道具也会更改。根据react-router-dom文档:

使用而不是为您创建新的React元素 组件属性,您可以传入一个要在 位置匹配。 render prop函数可以访问所有相同的对象 路线道具(比赛,位置和历史)作为组件渲染 道具。

这意味着当发生路线更改时,我们可以使用props.location.key获取更改密钥。将其传递给组件会使每次密钥更改时重新渲染组件。

答案 5 :(得分:1)

简单为:

System.Net.WebException: The remote server returned an 
    
error: (400) Bad Request.
    
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(WebRequest request)
    
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord()!
    
+ CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException

对我来说很好。定位到同一路径时:

<Route path="/my/path" render={(props) => <MyComp {...props} key={Date.now()}/>} />

即使我已经在this.props.history.push("/my/path"); 上,页面也会重新加载。

答案 6 :(得分:1)

这是一个骇人听闻的解决方案,不需要更新任何下游组件或更新很多路由。我真的不喜欢它,因为我觉得在React-Router中应该有一些东西可以为我处理。

基本上,如果链接是指向当前页面的,则单击...

  1. 等到当前执行之后。
  2. /refresh?url=<your url to refresh>替换历史记录。
  3. 让交换机监听/refresh路由,然后将其重定向回url查询参数中指定的url。

代码

首先在我的链接组件中

function MenuLink({ to, children }) {
    const location = useLocation();
    const history = useHistory();
    const isCurrentPage = () => location.pathname === to;
    const handler = isCurrentPage() ? () => {
        setTimeout(() => {
            if (isCurrentPage()) {
                history.replace("/refresh?url=" + encodeURIComponent(to))
            }
        }, 0);
    } : undefined;

    return <Link to={to} onClick={handler}>{children}</Link>;
}

然后在我的开关中

<Switch>
        <Route path="/refresh" render={() => <Redirect to={parseQueryString().url ?? "/"} />} />
        {/* ...rest of routes go here... */}
<Switch>

...其中parseQueryString()是我为获取查询参数而编写的函数。

答案 7 :(得分:1)

我找到了一个简单的解决方案。

<BrowserRouter forceRefresh={true} />

这会在点击任何链接时强制刷新。不幸的是,它是全局的,因此您无法指定仅刷新哪些链接/页面。

答案 8 :(得分:0)

我通过将新路由推入历史记录,然后将该路由替换为当前路由(或要刷新的路由)来解决此问题。这将触发react-router在不刷新整个页面的情况下“重新加载”路由。

<Link onClick={this.reloadRoute()} to={'/route-to-refresh'}>
    Click Me
</Link>

let reloadRoute = () => {
    router.push({ pathname: '/empty' });
    router.replace({ pathname: '/route-to-refresh' });
}

反应路由器通过使用浏览器历史记录进行导航而无需重新加载整个页面。如果您将路由强加到历史记录中,则React Router将检测到此情况并重新加载路由。更换空路径很重要,这样在推入后您的后退按钮不会将您带到空路径。

根据react-router,反应路由器库似乎不支持此功能,并且可能永远不会支持此功能,因此您必须以hacky的方式强制刷新。

答案 9 :(得分:0)

我现在能想到的是,

  1. 创建一个新组件,并包含Redirect react-router-dom包。

  2. 在此组件中,使用重定向到首选路由     <Redirect to={`/page-to/${props.match.params.id}`}>

    注意:要使用props.match.params.id,您需要将其包含在路线的“以下示例”中。

  3. 在任何路由上都包括链接并指向重定向路由。

以下示例:

import React from "react";
import { Redirect } from "react-router-dom";

const RedirectPage = props => {
  return <Redirect to={`/page-to/${props.match.params.id}`} 
    />;
};

export default RedirectPage;

在App.jsx上创建您的路线

<Route
  exact
  path="/redirect-page/:id"
  component={RedirectPage}
/>

然后您创建一个链接

<Link to={`/redirect-page/${id}`}>
  Click Me
</Link>

答案 10 :(得分:-1)

使用Rachita Bansal答案解决,但使用componentDidUpdate代替componentWillReceiveProps

componentDidUpdate(prevProps) {
    if (prevProps.location.pathname !== this.props.location.pathname) { window.location.reload();
    }
}

答案 11 :(得分:-1)

说实话,这些都不是真正的“思考React”。对于那些着眼于此问题的人来说,完成相同任务的更好的替代方法是使用组件状态。

将路由组件上的状态设置为布尔值或您可以跟踪的值:

<div class="box green">Green</div>
<div class="box red">Red</div>
<div class="box blue">Blue</div>
<div class="box black">Black</div>

当您要转到下一条路线时,只需更新状态并将渲染方法加载到所需的组件中即可。

答案 12 :(得分:-2)

您可以使用生命周期方法 - componentWillReceiveProps 单击链接时,位置道具的键将更新。所以,你可以做一个解决方法,如下所示,

/**
 * @param {object} nextProps new properties
 */
    componentWillReceiveProps = (nextProps)=> {
        if (nextProps.location.key !== this.props.location.key) {
            window.location.reload();
        }
    };

答案 13 :(得分:-2)

尝试仅使用锚标记href链接。在标签中使用target="_self"强制页面完全重新呈现。

答案 14 :(得分:-2)

我遇到了同样的问题,我通过使用 href 而不是 Link 解决了

<a href='/'>