即使链接URL发生更改,React Router也不会重新呈现

时间:2020-07-05 02:09:53

标签: reactjs url react-router

所以我有一个简单的帖子应用程序。我有一个名为Post.js的组件。会加载一个帖子。

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import Spinner from '../../common/Spinner';
import { getPost } from '../../../actions/postActions';
import PostDetails from './Post-Details';
import CommentForm from './CommentForm';
import CommentFeed from './CommentFeed';
import Navbar from "../../../components/layout/Navbar";



class Post extends Component {


  componentDidMount() {
    this.props.getPost(this.props.match.params.id);
  }

  render() {

    const { post, loading } = this.props.post;
    const { user } = this.props.auth;
    let postContent;

    if (post === null || loading || Object.keys(post).length === 0) {
      postContent = <Spinner />;
    } else if (user === null || Object.keys(user).length === 0) {
      postContent = (
        <div>
        <PostDetails post={post} showActions={false}/>
        <div className="commentsArea">
          <br />
          <CommentFeed postId={post._id} comments={post.comments} />
        </div>
      </div>
      )

    } else {
        postContent = (
          <div>
            <PostDetails post={post} showActions={false}/>
            <div className="commentsArea">

              <CommentForm postId={post._id} />
              <CommentFeed postId={post._id} comments={post.comments} />
            
            </div>
          </div>
        );
    }


    return (
      <div className="postSingle">
        <Navbar />

        <div className="container">
          <div className="row">
            <div className="col-md-12">
              {postContent}
            </div>
          </div>
        </div>
      </div>
    );
    
  }
}

Post.propTypes = {
  getPost: PropTypes.func.isRequired,
  post: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  post: state.post,
  auth: state.auth
});

export default connect(mapStateToProps, { getPost })(Post);


该组件只有几个子组件,其中PostDetails.js可显示帖子的实际详细信息,例如图片,标题正文,作者和标签。


import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import classnames from "classnames";
import Related from "./RelatedPosts"
import { Link } from "react-router-dom";
import { deletePost, addLike, removeLike } from "../../../actions/postActions";
import Moment from "react-moment";
import Truncate from "react-truncate";

export class PostItem extends Component {
  onDeleteClick(id) {
    this.props.deletePost(id);
  }

  onLikeClick(id) {
    this.props.addLike(id);
  }

  onUnlikeClick(id) {
    this.props.removeLike(id);
  }

  findUserLike(likes) {
    const { auth } = this.props;

    if (likes.filter(like => like.user === auth.user.id).length > 0) {
      return true;
    } else {
      return false;
    }
  }

  render() {
    const { post, auth, showActions } = this.props;
    const { isAuthenticated, user } = this.props.auth;

    const tags = post.tags.map((tag, index) => (
      <div key={index} className="p-3">
        <i className="fa fa-check" /> {tag}
      </div>
    ));

    const editbtn = (
      <Link to={{
        pathname:'/editpost',
        postProps:{
          id:post._id
        }
      }}>
        Edit
      </Link>
    )


    return (
      <React.Fragment>

        <div className="row">

          
          <div className="card card-body col-md-8">
            <div className="row">
              <div className="cardHeaderImage col-md-12 ">
                {post.headerimage === "" ? (
                  "  "
                ) : (
                  <img
                    src={post.headerimage}
                    className="card-img-top"
                    alt="..."
                  />
                )}
              </div>

              <div className="postHeadline col-md-12 ">
                <h3>
                  <span className="headlineTitle">{post.headline}</span>
                  <span className="commentsCount">
                    {post.comments.length} Comments
                  </span>
                </h3>
              </div>
            </div>

            <div className="postAuthor row">
              <h6>By {post.user.name}</h6>

              {/* <img src={post.avatar} alt=""/> */}

              <h6>
                Posted <Moment format="MM/DD/YYYY">{post.date}</Moment>
              </h6>

              {isAuthenticated && user.name === post.user.name ? editbtn : ""}
            </div>

            <div className="row">
              <div className="postText col-md-12">
                <p className="card-text">{post.text}</p>

                <br />

                <h3>Tags</h3>
                <p style={{ display: "flex" }}>{tags}</p>

                {showActions ? (
                  <span className="profileActions">
                    <button
                      onClick={this.onLikeClick.bind(this, post._id)}
                      type="button"
                      className="btn btn-concord mr-1"
                    >
                      <i
                        className={classnames("fas fa-thumbs-up", {
                          "text-info": this.findUserLike(post.likes),
                        })}
                      />
                      <span className="badge badge-concord">
                        {post.likes.length}
                      </span>
                    </button>

                    <button
                      onClick={this.onUnlikeClick.bind(this, post._id)}
                      type="button"
                      className="btn btn-concord mr-1"
                    >
                      <i className="text-secondary fas fa-thumbs-down" />
                    </button>

                    <Link to={`/post/${post._id}`} className="btn btn-sole mr-1">
                      Read More
                    </Link>

                    {post.user._id === auth.user.id ||
                    post.user === auth.user.id ? (
                      <button
                        onClick={this.onDeleteClick.bind(this, post._id)}
                        type="button"
                        className="btn btn-danger mr-1"
                      >
                        <i className="fas fa-times" />
                      </button>
                    ) : null}
                  </span>
                ) : null}
              </div>
            </div>
          </div>

          <Related tags={post.tags} postId={post} />
        

        </div>




        
      </React.Fragment>
    );
  }
}

PostItem.defaultProps = {
  showActions: true
};

PostItem.propTypes = {
  deletePost: PropTypes.func.isRequired,
  addLike: PropTypes.func.isRequired,
  removeLike: PropTypes.func.isRequired,
  post: PropTypes.object.isRequired,
  auth: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  profile: state.profile,
  auth: state.auth
});

export default connect(
  mapStateToProps,
  { deletePost, addLike, removeLike }
)(PostItem);


并且PostDetails具有子组件(RelatedPosts.js),该子组件呈现与当前加载的帖子相关的帖子的详细信息。我使用当前帖子的帖子标签,并在后端查询具有匹配标签的其他帖子。如果找到任何相关文章的预览详细信息,将显示在RelatedPosts.js中。在PostDetail.js组件中显示为侧边栏

import React, { Component } from 'react'
import { connect } from 'react-redux';
import { getRelatedPosts } from '../../../actions/postActions';
import Truncate from "react-truncate";
import { Link } from "react-router-dom";



export class RelatedPosts extends Component {

  componentDidMount() {

    const { tags, postId } = this.props;
    this.props.getRelatedPosts(tags);
  }
  

  render() {

    const { tags, postId } = this.props;
    const { posts } = this.props.post;

    let related = posts.map(post => {
      return (
        <div className="card" style={{ marginBottom: "20px" }}>
          <img className="card-img-top" src={post.headerimage} alt="" />
          <div className="card-body">
            <h4 className="card-title">{post.headline}</h4>
            <p className="card-text">
              <Truncate lines={2} ellipsis={<span>...</span>}>
                {post.text}
              </Truncate>
            </p>
            <Link to={`/post/${post._id}`} className="btn btn-sole mr-1">
                  Read More
            </Link>
            
          </div>
        </div>
      );
    });

    return (
      <div className="col-md-3 offset-1 card related">
      <h3>Related Posts</h3>


    <ul>
      {related}
    </ul>

    </div>
    )
  }
}

const mapStateToProps = state => ({
  post: state.post,
  auth: state.auth
});

export default connect(mapStateToProps, { getRelatedPosts })(RelatedPosts);

希望我对上述代码结构的解释是合理的。以上所有这些都很好。但是,当我单击相关帖子之一中的链接时。

来自RelatedPosts.js

<Link to={`/post/${post._id}`} className="btn btn-sole mr-1">
   Read More
</Link>

链接URL会适当更改,但是不会重新呈现任何内容。屏幕上仍显示相同的帖子。但是,当我刷新页面时,它将随后呈现我单击的相关帖子。我不知道为什么会这样。

这是来自我的App.js组件的相关代码,其中包含我的路由器

import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import jwt_decode from 'jwt-decode';
import setAuthToken from './utils/setAuthToken';
import { setCurrentUser, logoutUser } from './actions/authActions';
import { clearCurrentProfile } from './actions/profileActions';

import { Provider } from 'react-redux';
import store from './store';
import ScrollToTop from './ScrollToTop'

import PrivateRoute from './components/common/PrivateRoute';
import AuthorRoute from './components/common/AuthorRoute';
import Posts from './components/posts/all-users-posts/AllPosts';
import Post from './components/posts/post-single/Post';
import CreatePost from './components/posts/post-creation/CreatePost';
import EditPost from './components/posts/post-creation/EditPost';

class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <Router>
         <ScrollToTop>
          <React.Fragment>
             <Route exact path="/register" component={Register} />
              <Route exact path="/login" component={Login} />
              <Route exact path="/profiles" component={Profiles} />
              <Route exact path="/profile/:handle" component={Profile} />
              <Route exact path="/post/:id" component={Post} />
              <Route exact path="/allposts" component={Posts} />
              <Route exact path="/editpost/" component={EditPost} />

          </React.Fragment>
         </ScrollToTop>
        </Router>
      </Provider>

      );
  }
}

export default App;

这不是我的React的全部代码,而是与我的问题相关的代码。我唯一能想到的是,即使URL发生更改,当我单击链接时,它仍然使用相同的组件: <Route exact path="/post/:id" component={Post} /> 也许这至少是问题的一部分。

1 个答案:

答案 0 :(得分:1)

这是一个长期问题,混乱的组件命名。我懒于阅读所有内容,但我认为我的答案是正确的。 那是因为:

  • 路线'/post/:id' Post 组件
  • 匹配
  • 链接位于内部 Post组件

因此,当您单击它(位于 Post 组件中)时,React不会再次卸载并重新安装Post组件。只是 更新 。 因此它将调用更新生命周期方法,例如: Post

shouldComponentUpdate,render,componentDidUpdate ...

因此该解决方案使用 componentDidUpdate 方法获取新postId 并再次获取Post数据

相关问题