如何使用 React-Router 4.0 刷新当前路由?不重新加载整个页面

19
'react-router-dom'有刷新函数在这里,但我不知道如何调用此方法,他们格式良好的文档也没有解释这个问题。
window.location.reload() 对我没用,因为它也会清除应用程序存储。 我更改了一些数据,然后需要重新加载更新后的路线。
我也看过这个:https://github.com/ReactTraining/react-router/issues/1982 https://github.com/ReactTraining/react-router/issues/2243,这个线程正好讨论我的问题:https://github.com/ReactTraining/react-router/issues/4056,但仍然不知道怎么做。 这个基本函数不应该需要太多的努力,但是经过巨大的努力之后,我无法重新加载当前路线。
这是我的代码:
@inject('store') @observer
export default class PasswordInput extends Component {
    constructor (props) {
        super(props)
        this.setPwd = this.setPwd.bind(this)
        this.submit = this.submit.bind(this)
    }

    componentWillMount() {
        this.case = this.props.store.case

        this.setState({refresh: false})
    }
    setPwd(e) {
        // console.log(e)
        this.case.pwd = e.target.value

    }
    submit() {
        console.log(this.props.caseId)
        this.setState({refresh: true})

    }

    render() {
        return (
            <Container>
                <div>{this.state.refresh}</div>
                { (this.state.refresh) && <Redirect refresh={true} to={'/cases/' + this.props.caseId}></Redirect>}
                <br />
                <Grid columns="three">
                    <Grid.Row>
                        <Grid.Column key={2}>
                            <Form>
                                <label>Enter Password</label>
                                <input placeholder="empty"  type="text" onChange={this.setPwd} value={this.case.pwd}></input>                               

                                <Button name="Save" color="green" size="mini" 
                                style={{marginTop:'1em'}}
                                onClick={this.submit}>
                                    Submit
                                </Button>                               
                            </Form>
                        </Grid.Column>
                    </Grid.Row>
                </Grid>
            </Container>
        )
    }
}

2
“刷新”路由听起来像是 XY 问题。https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem 你实际上想要实现什么? - azium
你应该为此创建一个 jsfiddle。当其观察的数据变化时,该组件会重新渲染。这不是发生了吗? - Himanshu Jain
11个回答

14

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

if (routesEqual && forceRefresh) {
    router.push({ pathname: "/empty" });
    router.replace({ pathname: "/route-to-refresh" });
}

React路由器通过使用浏览器历史记录在不重新加载整个页面的情况下进行导航。如果你强制将一个路由添加到历史记录,React路由器会检测到并重新加载该路由。重要的是要替换空路由,以便在点击后退按钮时不会返回空路由。

根据react-router显示,似乎React路由器库不支持此功能,而且可能永远不会支持,因此你必须以一种欺骗性的方式强制刷新。


5
你可以使用这个小技巧。 像 history.push('/temp') 这样在历史记录中推入一个新的路径,然后立即调用 history.goBack() 下面是例子:
创建一个历史记录并将其传递给路由器:
import { createBrowserHistory } from "history";

export const appHistory = createBrowserHistory();

<Router history={appHistory}>
  <Route exact path="/" component={Home} />
  <Route path="/about" component={About} />
</Router>

然后在您的应用程序中的某个地方,更改历史记录:

appHistory.push('/temp');
appHistory.goBack();

这样做,路由路径将“保持”不变,并且会被刷新。


2

我也遇到了同样的问题,对于刷新是如何实现的一无所知。我的解决方案是执行以下两个步骤:

  1. 将新路径推送到历史记录中
  2. 重置所有状态

然后DOM会重新渲染你的路由。


2

我不知道react-router是否已经解决了这个问题,但在我的情况下,我会创建一个新的路径名为refresh,并在组件第一次渲染时返回。

<Route
    path="/refresh"
    exact
    component={() => {
       useEffect(() => history.goBack(), []);
       return <></>;
    }}
 />

当我想要刷新路由时,我只需要点击刷新路由,然后它会返回并渲染出新的重新加载结果;


2
这是我实现它的方法:
if (currentUrl == newUrl) {
    props.history.push("/temp");
    props.history.goBack();
}

1
我在我们的应用程序中使用了键和状态来解决这个问题。
在我的情况下,即使菜单已经处于活动状态,我们也希望在单击相同菜单时进行刷新而不必完全重新加载。
因此,在我们的菜单单击中,我有这段代码。它不必是uuid,只要每次触发时都会更改即可。它也不必是具有reloadKey属性的对象,这取决于你。它可以只是一个简单的字符串,我只是以这种方式编码它。
push({state: {reloadKey: uuid()}}); 

然后,我在路由中设置了键。

PrivateRoute是我的包装器,它将来自react-router-dom的Route进行了封装。

const {state: { reloadKey } = {}}  =  location;
<PrivateRoute key={reloadKey} path="/path" component={Component} />

由于密钥已更改,这将触发组件重新挂载而不会触发完整页面重新加载。

1

只有这个对我起作用:

reloadOrNavigate = () => {
  const { history, location } = this.props;
  if (location.pathname === '/dashboard') {
    history.replace(`/reload`);
    setTimeout(() => {
      history.replace(`/dashboard`);
    });
  } else {
    history.push('/dashboard');
  }
};

答案与之前的类似,但我需要添加setTimeout函数才能使其工作。在我的情况下,如果我在/dashboard页面上,必须通过单击徽标来刷新当前URL。首先,它转到额外的路由/reload(名称由您决定),然后立即返回。页面变为白色不到一秒钟,然后重新加载数据出现。浏览器没有重新加载,仍然是SPA,这很好。

1
尽管这可能会回答问题,但您应该编辑您的答案,包括您的代码如何回答问题,以为未来的读者提供上下文。单独的代码块对那些以后可能遇到相同问题的人来说并不立即有用。 - Hoppeduppeanut

1

以下是我的解决方案,使用了react-router-dom的“Redirect”:

<Route key={props.notifications.key} path={props.notifications.path} exact render={() => <Redirect to={props.notifications.path + "/update"}/>}/>
<Route key={props.notifications.key + "/update"} path={props.notifications.path + "/update"} exact render={() => <props.notifications.component apis={props.notifications.apis}/>}/>

0

我在开头使用重定向,它会从URL末尾删除尾随斜杠

 <Redirect key={0} from="/:url*(/+)" to={pathname.slice(0, -1)} />

然后,您可以在路由路径的末尾添加斜杠并且每次重新加载时都会生效。

0

好的,我之前尝试过几乎所有的答案,但都没有起作用。这是我能强制重新加载的唯一方法

我正在使用redux,但您也可以使用任何您喜欢的状态管理

1- 将布尔值设置为false

2- 为您的链接/按钮添加一个onClick函数,该函数将把布尔值设置为true

3- 将该布尔变量添加到useEffect()

这将触发重新渲染

useEffect(() => {
   // Do stuff...
},[forceReload])

const forceReload = () => {
   dispatch({ type: RELOAD });
   // OR useState or whatever you want
   setForceReload(true);
}


...
<Link onClick={forceReload} to="/my-path-that-does-not-reload">
   Reload Page
</Link>

对于链接和HTML按钮标签,这对我很有效。


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