简体   繁体   中英

Routes unable to load using react-router

I'm designing a simple application using create-react-app and I've recently delved into the power of react-router . However, I'm having an issue with pages getting stuck trying to load, and I'm not sure why.

I've got a Navbar component, for which I'll condense the gist of what it is.

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

import BlogPost from '../Pages/BlogPost';

// Condensed because a lot of the detail is unnecessary and no-one likes blocks of unneeded code
class Navbar extends React.Component {
  render() {
    return (
      <Router>
        <nav>
          <div id="navigationlinks">
            <ul id="navlinks-left">
                <li className="nav-item"><Link to='/'>Home</Link></li>
              <li className="nav-item"><Link to='/about'>About</Link></li>
            </ul>
          </div>
        </nav>

        <Switch>
          <Route path='/post' component={BlogPost} />
          <Route path='/about'>
            <About />
          </Route>
        </Switch>
      </Router>
    );
  }
}

function About() {
  return <h2>The about page.</h2>;
}

export default Navbar;

BlogPost represents a component that is a page in itself. The code looks like this. Again, I'll abstract away from the stuff that's not relevant.

import React from 'react';

import Navbar from '../Components/Navbar';
// Other components on this page. None of them reference the navbar or contain a router of their own.
import BlogBox from '../Sections/BlogBox';
import CommentForm from '../Components/CommentForm';
import CommentBox from '../Sections/CommentBox';

class BlogPost extends React.Component {
    
    getBlogPost(address) {
        // Gets blog data (like the title, description, content, image, etc.) using 'fetch' from 
        // an API at 'address'. Abstracted away because this isn't relevant.
    }

    componentDidMount() {
        console.log("Blog post mounted!");
        this.getBlogPost("http://localhost:8080/api/blog/samplepost");
    }

    render() {
        return (
            <div className="blog-post">
                <Navbar />
                <BlogBox post={this.state ? this.state.post : ""}/>
                <CommentForm />
                <CommentBox comments={this.state ? this.state.comments: ""} />
            </div>
        );
    }   

}

export default BlogPost;

The homepage of my application is located at '/' . It's rendered in my index.js file, the code of which is below.

import React from 'react';
import ReactDOM from 'react-dom';

import BlogHome from './Pages/BlogHome';
import BlogPost from './Pages/BlogPost';

ReactDOM.render(
    <BlogHome />,
    document.getElementById('root')
);

The homepage renders fine, but when I go to navigate to /post , the application attempts to load the page indefinitely, and eventually times out, being unable to do so.

Notice how the BlogPost page component renders the Navbar component, which in turn has a path /post which renders the BlogPost object? I'm not sure if I'm able to change this. Could this be the reason why the /post path can't load?

What concerns me the most here is that I eventually would like to add additional pages which will not only contain this same Navbar , but for which their page links also exist in this Navbar. For example, if I add an About page, this page will not only contain the Navbar, but its link will also be present in this Navbar!

Is there a way I can keep such self-page links in the Navbar, without the recursive render loop occurring?

Issue

You are creating a cycle between rendering Navbar and BlogPost when the current path matches "/post`.

In other words BlogHome renders a Navar which renders a BlogPost which then renders another Navbar and another BlogPost ad nauseam.

Solution

Restructure your navbar and routes a bit to split them out

index.js

Since BlogHome sounds like a page it should be placed on its own route. Move Router here to wrap entire app. Render BlogHome path last as that matches all path prefixes, so it will render if no other route is matched above it by the Switch .

ReactDOM.render(
    <Router>
      <Switch>
        <Route path='/post' component={BlogPost} />
        <Route path='/about'>
          <About />
        </Route>
        <Route path="/" component={BlogHome} />
      </Switch>
    </Router>,
    document.getElementById('root')
);

Navbar

Remove the router and routes, leave links only.

class Navbar extends React.Component {
  render() {
    return (
      <nav>
        <div id="navigationlinks">
          <ul id="navlinks-left">
              <li className="nav-item"><Link to='/'>Home</Link></li>
            <li className="nav-item"><Link to='/about'>About</Link></li>
          </ul>
        </div>
      </nav>
    );
  }
}

Now each page should be free to render a Navbar or not.

try to remove Navbar in your BlogPost component, because when the location changes it will switch component here

   <Switch>
      <Route path='/post' component={BlogPost} />
      <Route path='/about'>
        <About />
      </Route>
   </Switch>

and

   <nav>
      <div id="navigationlinks">
          <ul id="navlinks-left">
                <li className="nav-item"><Link to='/'>Home</Link></li>
            <li className="nav-item"><Link to='/about'>About</Link></li>
         </ul>
      </div>
   </nav>

will persisit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM