嵌套的React Router组件不会在新页面上呈现

时间:2018-10-22 01:21:14

标签: reactjs react-router

我有一个包含主要组件的react应用。 ,其中包含带有导航栏标记的元素。

//app.js
    import React, { Component } from 'react';
    import {
      Route,
      NavLink,
      BrowserRouter,
      Switch,
    } from "react-router-dom";

    import Home from './components/home';
    import Create from './components/create';
    import './App.css';

    const pathBase = 'http://127.0.0.1:8000';
    const pathSearch = '/posts/';

    class App extends Component {
      constructor(props) {
        super(props);

        this.state = {
          posts: [],
          post: null,
          error: null,
        }

      }


      setPostsState = result => {
        this.setState({ posts: result})
      }

      setPostState = post => {
        this.setState({ post: post});
        console.log(this.state.post)

      }

      retrievePost = (event, post) => {
        event.preventDefault();
        this.fetchPost(post);

      }

      deletePosts = id => {
        fetch(`${pathBase}${pathSearch}${id }`, { method: 'DELETE'})
        .then(res => res.status === 204 ? this.fetchPosts() : null)
      }

      editPosts = id => {
        fetch(`${pathBase}${pathSearch}${id }`, { method: 'PUT'})
        .then(res => res.status === 204 ? this.fetchPosts() : null)
      }

      fetchPost = (post) => {
        fetch(`${pathBase}${pathSearch}${post.id}`)
          .then(response => response.json())
          .then(result => this.setPostState(result))
          .catch(error => console.log(error));
      }

      fetchPosts = () => {
        fetch(`${pathBase}${pathSearch}`)
          .then(response => response.json())
          .then(result => this.setPostsState(result))
          .catch(error => this.setState({ error: error }));
      }

      componentDidMount() {
        this.fetchPosts();
      }


      render() {
        const { posts, error } = this.state;

        if (error) {
          return <div className="container">
                  <h3>Error: {error.message}</h3>
                </div>;
        }

        return (
          <BrowserRouter>
            <div className="container">
            <header>
              <nav className="navbar navbar-expand-md navbar-light bg-light">
                <a className="navbar-brand" href="">Django Rest API</a>
                <div className="collapse navbar-collapse" id="navbarSupportedContent">
                  <ul className="navbar-nav mr-auto">
                    <li className="nav-item active">
                      <NavLink to="/posts">Posts</NavLink>
                    </li>
                    <li className="nav-item">
                      <NavLink to="/create">Create</NavLink>
                    </li>
                  </ul>
                </div>
              </nav>
            </header>
            <Switch>

            <Route path="/create" 
                   render={(props) => 
                  <Create {...props}
                    fetchPosts={this.fetchPosts} 
                  />
                } 
            />

               <Route path="/posts" 
                render={(props) => 
                  <Home {...props} 
                    posts={posts} 
                    deletePost={this.deletePosts} 
                  />
                } 
            />

            </Switch>

          </div>
          </BrowserRouter>

        );
      }
    }

    export default App;

还有一个(使用React-Router v4),其中path =“ / posts”呈现了一个Component。该组件由一个列表组成,该列表映射了从数据库获得的博客文章。每个帖子均显示为卡片,并带有帖子名称作为链接,当用户单击时,应调出组件以显示帖子详细信息。

// components/home.js
import React, { Component } from 'react';
import Post from './post';
import {
    Route,
    NavLink,    
  } from "react-router-dom";

class Home extends Component {


    render() {
        const ulStyle = { listStyleType: 'none' }
        const { deletePost, posts } = this.props;
        const match = this.props;
        console.log(match)

        return (
            <ul style={ ulStyle }>
            <h3>Posts</h3>
            {posts.map(post =>
            <li 
                key={posts.indexOf(post)}
                value={post.id} 
            >
              <div className="card">
                <div className="card-body">
                    <NavLink to={`/posts/${post.id}`}>{post.title} 
  </NavLink>, Created: {post.timestamp}
                <button type="button"
                  onClick={() => deletePost(post.id)} 
                  className="float-right btn btn-outline-danger btn-sm"
                >
                  Delete
                </button>
                </div>

                </div>
              </li>


              )}

              <Route exact path={`/posts/:postId`} render={(props) => 
 (<Post {...props} posts={posts}/>)}/>   

          </ul>
        );
    }
}

export default Home;

我无法让post组件在新页面上呈现。当前,如果用户单击链接,则组件将在现有页面(组件)的底部呈现。我需要Post组件在一个全新的页面上呈现。我是怎么做到的?

import React, { Component } from 'react';

class Post extends Component {

    render() {  
        const { children, match, posts} = this.props;
        console.log(match);
        console.log(posts);

        const p = (posts) => {
            posts.find(post => post === match.postId)
        }

        return (
                <div>
                    {match.params.postId}
                    <p>HELLO WORLD</p>
                </div>
         );
        }
    }


export default Post;

2 个答案:

答案 0 :(得分:1)

您看到的是React Router嵌套路由的预期行为。嵌套路由的内容将作为其父组件的一部分呈现。

这样设计,以便在导航时重新渲染的次数保持最少(当嵌套路线更改时,父组件的内容不会重新渲染)。

如果要更改整个页面的内容,则不应使用嵌套路由。只需将您拥有的所有路线放在Switch组件下。换句话说,将您的单个发布路线移至App组件。

答案 1 :(得分:0)

您应该对路由器组件有一个div。例如

<Router>
    <div className = "app">
     <nav />
      <div className = "container">
       //routes to be render here

     <Route exact path = "/sample" component = {Sample} />
      </div>
     <footer />
    </div>
   </Router>

,以便该组件将在页面中间呈现,并在路线更改时删除当前组件。