React Router V4 - 页面不会在更改的路由上重新呈现 [英] React Router V4 - Page does not rerender on changed Route

查看:65
本文介绍了React Router V4 - 页面不会在更改的路由上重新呈现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

import React, { Component } from 'react';从反应路由器"导入{路由,重定向}从 './LocationPicker' 导入 LocationPicker导出默认类 LocationDisplay 扩展组件 {构造函数(){极好的();this.setLocation = this.setLocation.bind(this);this.state = {重定向:假};}设置位置(值){this.setState({locationId: value});if (this.state.locationId != value) {this.setState({redirect : true})};}componentWillMount() {this.setState({locationId: this.props.match.params.locationId,});}使成为 () {返回 (this.state.redirect?<重定向推送到={{路径名:`/location/${this.state.locationId}`}}/>:<div><位置选择器returnLocation={this.setLocation}locationId={this.state.locationId}/><h1>请在下面找到对{this.state.locationId}的所有建议</h1>

)}}

这里是我的路线:

从'react'导入React;进口 {BrowserRouter 作为路由器,路线,关联来自'反应路由器-dom';从'react-dom'导入{渲染};从'./App'导入应用程序;从'./LocationPicker'导入LocationPicker;从 './LocationDisplay' 导入 LocationDisplay;Meteor.startup(() => {使成为(<路由器><div><路由精确路径=/"组件={LocationPicker}/><Route path="/location/:locationId" component={LocationDisplay}/>

</路由器>,document.getElementById('render-target'));});

更新:

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

render() {返回 (this.state.redirect?<链接到={{路径名:`/location/${this.state.locationId}`}}/>:<div><位置选择器returnLocation={this.setLocation}locationId={this.state.locationId}/><h1>请在下面找到有关 {this.state.locationId} 的所有建议</h1>

)}

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

干杯和谢谢

解决方案

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

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

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

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

export default class LocationDisplay extends Component {构造函数(){极好的();}设置位置(值){this.props.history.push(`/location/${value}`);}使成为 () {const locationId = this.props.match.params.locationId返回 (<div><位置选择器returnLocation={this.setLocation}locationId={locationId}/><h1>请在下面找到关于{locationId}的所有建议</h1>

)}}

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

I am building a small App to learn React with Meteor. The user is asked to input a location, based on this location the user gets routed to a new page, where the location is displayed on the top of the page and some data from the database based on that location (not yet, this is my next step). I store the location in state on the component. Now it would be nice if the user could change the location. This is easy: just update state, e voilá. Or so I thought. The problem now is that the URL doesn't update, which looks dumb. I then thought: "Okay, lets check on click if old location (in state) and new location (from input) are different, and if so set a redirect state" In my render function if redirect is set I would just route the user to the same page again, but now the page won't reload. Any Ideas?

I know there are a thousand questions on react router v4 out there right now, because they just updated the version recently. I have been reading documentation for the last hours and just can't wrap my head around it.

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>
        )
    }
}

And here my Routes:

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')
    );
});

Update:

I tried using <Link> instead of <Redirect>, however this has the same effect. Even more so, it does not update URL at all now.

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>
        )
    }

Any explanation regarding the problem in basic language would also be extremely appreciated. I am just not there yet :(

Cheers and thx alot

解决方案

You can't expect to change the route just by changing the state. Even with the <Redirect> approach that you have used, it only make an infinite redirect loop by setting this.state.redirect true. Because Route use same LocationDisplay instance with each redirect and this.state.redirect will be always true. However, react-router automatically directs this redirect loop and renders a blank.

The correct way to change routes in react-router is use push method in history object. You can simply call push method with your new path name as follows.

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

Also, I don't understand why you keep locationId in your state. It's already in your props at this.props.match.params.locationId. So there is no point of keep same data in two places because having a single source of truth is ideal. Otherwise, you always have to write additional code lines to keep locationId in state and props sync. So I suggest you to, change your approach to something like this.

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>
    )
  }
}

(This code is just to get an idea. I didn't test this code as I don't have other parts. If you can provide codepen or jsfiddle with your current implementation I can update it to work.)

这篇关于React Router V4 - 页面不会在更改的路由上重新呈现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆