React Router V4 - 页面不会在更改的路由上重新呈现

IT技术 reactjs react-router
2021-05-23 14:47:14

我正在构建一个小应用程序来学习使用 Meteor 进行 React。用户被要求输入一个位置,基于这个位置,用户被路由到一个新页面,该位置显示在页面顶部,以及基于该位置的数据库中的一些数据(还没有,这是我的下一步)。我将位置存储在组件上的状态中。现在,如果用户可以更改位置,那就太好了。这很简单:只需更新状态,瞧。或者我是这么想的。现在的问题是 URL 没有更新,这看起来很愚蠢。然后我想:“好吧,让我们检查一下旧位置(状态)和新位置(来自输入)是否不同,如果是这样,请设置重定向状态”在我的渲染函数中,如果设置了重定向,我只会路由用户再次到同一页面,但现在页面不会重新加载。有任何想法吗?

我知道现在有上千个关于 react router v4 的问题,因为他们最近才更新了版本。过去几个小时我一直在阅读文档,但无法理解它。

import React, { Component } from 'react';
import { Route, Redirect } from 'react-router'
import LocationPicker from './LocationPicker'

export default class LocationDisplay extends Component {
    constructor () {
        super();
        this.setLocation = this.setLocation.bind(this);
        this.state = {redirect: false};
    }

    setLocation(value) {
        this.setState({locationId: value});
        if (this.state.locationId != value) {
            this.setState({redirect : true})
        };
    }

    componentWillMount() {
        this.setState({
            locationId: this.props.match.params.locationId,
        });
    }

    render () {
        return (
            this.state.redirect 
            ? 
            <Redirect push to={{
                pathname: `/location/${this.state.locationId}`
            }}/> 
            :
            <div>
                <LocationPicker 
                    returnLocation={this.setLocation} 
                    locationId={this.state.locationId}
                />
                <h1>Please find below all recommendations for {this.state.locationId}</h1>
            </div>
        )
    }
}

这里是我的路线:

import React from 'react';
import {
  BrowserRouter as Router,
  Route,
  Link
} from 'react-router-dom';
import { render } from 'react-dom';

import App from './App';
import LocationPicker from './LocationPicker';
import LocationDisplay from './LocationDisplay';

Meteor.startup(() => {
    render(
        <Router>
            <div>
                <Route exact path="/" component={LocationPicker}/>
                <Route path="/location/:locationId" component={LocationDisplay}/>
            </div>
        </Router>,
         document.getElementById('render-target')
    );
});

更新:

我尝试使用<Link>而不是<Redirect>,但这具有相同的效果。更重要的是,它现在根本不更新 URL。

render () {
        return (
            this.state.redirect 
            ? 
            <Link to={{
                pathname: `/location/${this.state.locationId}`
            }}/>
            :
            <div>
                <LocationPicker 
                    returnLocation={this.setLocation} 
                    locationId={this.state.locationId}
                />
                <h1>Please find bellow all recommendations for {this.state.locationId}</h1>
            </div>
        )
    }

任何关于基本语言问题的解释也将不胜感激。我只是还没到那里:(

干杯和谢谢

2个回答

您不能期望仅通过更改state. 即使使用<Redirect>您使用方法,它也只能通过设置this.state.redirecttrue 来进行无限重定向循环因为Route每次重定向this.state.redirect使用相同的 LocationDisplay 实例,并且始终为真。但是,react-router 会自动引导此重定向循环并呈现空白。

在 react-router 中更改路由的正确方法是pushhistory对象中使用方法您可以简单地push使用新路径名调用方法,如下所示。

setLocation(value) {
  this.props.history.push(`/location/${value}`);
}

另外,我不明白你为什么保留locationId在你的state. 它已在您的propsat 中this.props.match.params.locationId所以没有必要在两个地方保存相同的数据,因为拥有单一的真实来源是理想的。否则,你总是要编写额外的代码行,以保持locationIdstateprops同步。所以我建议你,改变你的方法来做这样的事情。

export default class LocationDisplay extends Component {
  constructor () {
      super();
  }

  setLocation(value) {
    this.props.history.push(`/location/${value}`);
  }

  render () {
    const locationId = this.props.match.params.locationId
    return (
      <div>
        <LocationPicker 
          returnLocation={this.setLocation} 
          locationId={locationId}
        />
        <h1>Please find below all recommendations for {locationId}</h1>
      </div>
    )
  }
}

(这段代码只是为了得到一个想法。我没有测试这段代码,因为我没有其他部分。如果你能提供codepenjsfiddle与你当前的实现,我可以更新它以工作。)

对于那些遇到此问题与终极版,您的包裹connectwithRouter,如下所示:https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/blocked-updates.md