【问题标题】:Nested React Router Component Won't Render on New Page嵌套的 React 路由器组件不会在新页面上呈现
【发布时间】:2019-03-26 01:18:14
【问题描述】:

我有一个由主组件组成的反应应用程序。 ,它包含一个带有导航栏标记的元素。

//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;

【问题讨论】:

    标签: reactjs react-router


    【解决方案1】:

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

    这样设计是为了在导航时将重新渲染的次数保持在最低限度(嵌套路由更改时不会重新渲染父组件的内容)。

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

    【讨论】:

    • 感谢您的回复!
    • 这个答案以及这篇文章medium.com/@pshrmn/… 帮助我解决了这个问题,组件现在呈现在全新的页面上。
    【解决方案2】:

    你应该有一个路由器组件的 div。例如

    <Router>
        <div className = "app">
         <nav />
          <div className = "container">
           //routes to be render here
    
         <Route exact path = "/sample" component = {Sample} />
          </div>
         <footer />
        </div>
       </Router>
    

    这样组件将在页面中间呈现,并在路由发生变化时移除当前组件。

    【讨论】:

    • 我认为路由器组件需要放在一个封闭标签中,它们已经是。这个答案没有帮助。
    猜你喜欢
    • 2021-05-19
    • 1970-01-01
    • 2019-10-09
    • 1970-01-01
    • 2021-11-14
    • 1970-01-01
    • 1970-01-01
    • 2021-09-11
    相关资源
    最近更新 更多