react-router链接在同一路径上访问时不会导致重新渲染

IT技术 javascript reactjs ecmascript-6 react-router
2021-05-05 08:08:06

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

  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')但是他不会看到页面重新呈现,他也没有看到最新的评论,因为该页面什么都不做。
4个回答

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

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

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

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

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

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

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

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

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

我可能会尝试这样的事情(伪代码,因为我不知道你是如何获得新评论或通过 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")
);

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

这为我解决了问题:

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

<Router>  
 <Switch>

     <Redirect from="/x_walls/:user_Id" to='/walls/:user_Id'/>
     <Route path="/walls/:user_Id" exact render={(props) => <Wall {...props}/> }/>           

  </Switch>

</Router>

当你想调用“walls”时,你只需调用“x_walls”

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

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