Search code examples
javascriptreactjsreact-routerreact-bootstrap

ReactJS Bootstrap Navbar and Routing not working together


I am trying to create a simple Webapp using ReactJS, and I wanted to use the Navbar provided by React-Bootstrap.

I created a Navigation.js file containing a class Navigation to separate the Navbar and the Routing from the App.js file. However, both parts do not seem to work. When I load the page, it is just empty, there is no Navbar. Can anyone spot a mistake?

Navigation.js:

import React, { Component } from 'react';
import { Navbar, Nav, Form, FormControl, Button, NavItem } from 'react-bootstrap';
import { Switch, Route } from 'react-router-dom';
import { Home } from './Page';

class Navigation extends Component {
    render() {
        return (
            <div>
                <div>
                    <Navbar>
                        <Navbar.Brand href="/">React-Bootstrap</Navbar.Brand>
                        <Navbar.Collapse>
                            <Nav className="mr-auto">
                                <NavItem eventkey={1} href="/">
                                    <Nav.Link href="/">Home</Nav.Link>
                                </NavItem>
                            </Nav>
                            <Form inline>
                                <FormControl type="text" placeholder="Search" className="mr-sm-2" />
                                <Button variant="outline-success">Search</Button>
                            </Form>
                        </Navbar.Collapse>
                    </Navbar>
                </div>
                <div>
                    <Switch>
                        <Route exact path='/' component={Home} />
                        <Route render={function () {
                            return <p>Not found</p>
                        }} />
                    </Switch>
                </div>
            </div>
        );
    }
}

export default Navigation;

App.js:

import React, { Component } from 'react';
import Navigation from './components/routing/Navigation';



class App extends Component {
  render() {
    return (
      <div id="App">
        <Navigation />
      </div>
    );
  }
}

export default App;

I tried using a NavItem containing a LinkContainer from react-router-bootstrap already, which led to the same result.

Just for completeness, Page.js:

import React, { Component } from 'react';
import { Link } from 'react-router-dom';

export const Page = ({ title }) => (
    <div className="App">
      <div className="App-header">
        <h2>{title}</h2>
      </div>
      <p className="App-intro">
        This is the {title} page.
      </p>
      <p>
        <Link to="/">Home</Link>
      </p>
      <p>
        <Link to="/about">About</Link>
      </p>
      <p>
        <Link to="/settings">Settings</Link>
      </p>
    </div>
);


export const About = (props) => (
    <Page title="About"/>
);

export  const Settings = (props) => (
    <Page title="Settings"/>
);

export const Home = (props) => (
    <Page title="Home"/>
);

Solution

  • First of all, in your snippets it doesn't seem like you're wrapping your code in a Router, so you should make sure that you're doing that inside App or in ReactDOM.render:

    import { BrowserRouter } from 'react-router-dom';
    
    ReactDOM.render(
      <BrowserRouter>
        <App />
      </BrowserRouter>, 
      rootElement
      );
    

    Next, your specific problem is that you're rendering react-bootstrap's Nav.Link instead of react-router's Link component, so the router is not picking up your route changes. Fortunately, react-bootstrap provides a render prop in most of its components to specify which component or element you want to render if you don't want the default. Switch to something like this:

    import { Switch, Route, Link } from 'react-router-dom';
    
    class Navigation extends Component {
      render() {
        return (
          <div>
            <div>
              <Navbar>
                <Navbar.Brand as={Link} to="/" >React-Bootstrap</Navbar.Brand>
                <Navbar.Collapse>
                  <Nav className="mr-auto">
                    <NavItem eventkey={1} href="/">
                      <Nav.Link as={Link} to="/" >Home</Nav.Link>
                    </NavItem>
                  </Nav>
                  <Form inline>
                    <FormControl type="text" placeholder="Search" className="mr-sm-2" />
                    <Button variant="outline-success">Search</Button>
                  </Form>
                </Navbar.Collapse>
              </Navbar>
            </div>
            <div>
              <Switch>
                <Route exact path='/' component={Home} />
                <Route render={function () {
                  return <p>Not found</p>
                }} />
              </Switch>
            </div>
          </div>
        );
      }
    }