javascript 反应路由器链接在同一路径上访问时不会导致重新渲染

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/52099437/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 09:49:54  来源:igfitidea点击:

react router Link doesn't cause rerender when visited on the same path

javascriptreactjsecmascript-6react-router

提问by Hoknimo

I'm using react router v4, had some issue reloading the page (not window.location.reload). I better give a real use case to explain the issue, we use a social network app as the example:

我正在使用 react router v4,在重新加载页面(不是 window.location.reload)时遇到了一些问题。我最好给出一个真实的用例来解释这个问题,我们以一个社交网络应用程序为例:

  1. user A commented a post by user B, a notification appear in user B page.
  2. user B clicked on the notification, we do this.props.history.push('/job/' + id'), it worked, hence user B went to job/123page.
  3. user A commented again, new notification appear in user B page, while user B still remain on the job/123page, he clicked on the notification link and triggered this.props.history.push('/job' + id'). But he won't see the page rerender, he DID NOT see the latest comment because the page does nothing.
  1. 用户 A 评论了用户 B 的帖子,通知出现在用户 B 页面中。
  2. 用户 B 点击了通知,我们这样做了this.props.history.push('/job/' + id'),它起作用了,因此用户 B 转到了job/123页面。
  3. 用户A再次评论,新的通知出现在用户B页面,而用户B还在job/123页面上,他点击了通知链接并触发了this.props.history.push('/job' + id')。但是他不会看到页面重新呈现,他也没有看到最新的评论,因为该页面什么都不做。

回答by mHymanson

You are describing 2 different kinds of state changes.

您正在描述 2 种不同的状态变化。

In the first scenario, when user B is notat the /job/:idpage and he clicks a link you get a URL change, which triggers a state change in the router, and propagates that change through to your component so you can see the comment.

在第一种情况下,当用户B没有/job/:id网页和他点击你得到一个URL变化,这触发了路由器的状态变化的联系,以及传播这种变化通过对您的组件,所以你可以看到评论。

In the second scenario, when user B is already atthe /job/:idpage and a new comment comes through, the URL doesn't need to change, so clicking on a link won't change the URL and won't trigger a state change in the router, so you won't see the new content.

在第二种情况下,当用户B已经在/job/:id页面和新的注释来通过,该URL并不需要改变,那么点击链接将不会更改URL,并不会触发的状态变化路由器,因此您将看不到新内容。

I would probably try something like this (pseudo code because I don't know how you're getting new comments or subscribing via the websocket):

我可能会尝试这样的事情(伪代码,因为我不知道你是如何获得新评论或通过 websocket 订阅的):

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";

class Home extends React.Component {
  render() {
    return (
      <div>
        <h1>The home page</h1>

        {/* This is the link that the user sees when someone makes a new comment */}
        <Link to="/job/123">See the new comment!</Link>
      </div>
    );
  }
}

class Job extends React.Component {
  state = { comments: [] };

  fetchComments() {
    // Fetch the comments for this job from the server,
    // using the id from the URL.
    fetchTheComments(this.props.params.id, comments => {
      this.setState({ comments });
    });
  }

  componentDidMount() {
    // Fetch the comments once when we first mount.
    this.fetchComments();

    // Setup a listener (websocket) to listen for more comments. When
    // we get a notification, re-fetch the comments.
    listenForNotifications(() => {
      this.fetchComments();
    });
  }

  render() {
    return (
      <div>
        <h1>Job {this.props.params.id}</h1>
        <ul>
          {this.state.comments.map(comment => (
            <li key={comment.id}>{comment.text}</li>
          ))}
        </ul>
      </div>
    );
  }
}

ReactDOM.render(
  <BrowserRouter>
    <Switch>
      <Route exact path="/" component={Home} />
      <Route path="/job/:id" component={Job} />
    </Switch>
  </BrowserRouter>,
  document.getElementById("app")
);

Now the page will get updated in both scenarios.

现在页面将在两种情况下更新。

回答by Abu Shumon

It seems to be a common scenario in many cases. It can be tackled using many different approaches. Check this stackoverflow question. There are some good answers and findings. Personally this approachmade more sense to me.

在很多情况下,这似乎是一个常见的场景。可以使用许多不同的方法来解决它。检查这个stackoverflow 问题。有一些很好的答案和发现。就个人而言,这种方法对我来说更有意义。

location.keychanges every single time whenever user tries to navigate between pages, even within the same route. To test this place below block of code in you /jod/:idcomponent:

location.key每当用户尝试在页面之间导航时,即使在同一个route. 要在组件中的代码块下方测试此位置/jod/:id

componentDidUpdate (prevProps) {
    if (prevProps.location.key !== this.props.location.key) {
      console.log("... prevProps.key", prevProps.location.key)
      console.log("... this.props.key", this.props.location.key)
    }
  }

I had this exact same situation. Updated state in componentDidUpdate. After that worked as expected. Clicking on items within the same route updates state and displays correct info.

我有这种完全相同的情况。中的更新状态componentDidUpdate。之后按预期工作。单击同一路线内的项目会更新状态并显示正确的信息。

I assume (as not sure how you're passing/updating comments in /job/:id) if you set something like this in your /job/:idcomponent should work:

我假设(因为不确定你是如何在 中传递/更新评论的/job/:id)如果你在你的/job/:id组件中设置了这样的东西应该可以工作:

componentDidUpdate (prevProps) {
    if (prevProps.location.key !== this.props.location.key) {

      this.setState({
        comments: (((this.props || {}).location || {}).comments || {})
      })
    }
  }

回答by Soroush Chehresa

You should watch updating postIdin componentWillUpdatelife cycle and do something from here like this:

您应该观察生命周期中的更新postIdcomponentWillUpdate并从这里开始执行以下操作:

  componentWillUpdate(np) {
    const { match } = this.props;
    const prevPostId = match.params.postId;
    const nextPostId = np.match.params.postId;
    if(nextPostId && prevPostId !== nextPostId){
      // do something
    }
  }