ReactJS Bootstrap Navbar y Routing no funcionan juntos

9 minutos de lectura

Estoy tratando de crear una aplicación web simple usando ReactJS, y quería usar el Navbar proporcionado por React-Bootstrap.

creé un Navigation.js archivo que contiene una clase Navigation para separar el Navbar y el enrutamiento desde el App.js archivo. Sin embargo, ambas partes no parecen funcionar. Cuando cargo la página, está vacía, no hay barra de navegación. ¿Alguien puede detectar un error?

Navegación.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="https://stackoverflow.com/">React-Bootstrap</Navbar.Brand>
                        <Navbar.Collapse>
                            <Nav className="mr-auto">
                                <NavItem eventkey={1} href="https://stackoverflow.com/">
                                    <Nav.Link href="https://stackoverflow.com/">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="https://stackoverflow.com/" component={Home} />
                        <Route render={function () {
                            return <p>Not found</p>
                        }} />
                    </Switch>
                </div>
            </div>
        );
    }
}

export default Navigation;

Aplicación.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;

Intenté usar un NavItem que contiene un LinkContainer de react-router-bootstrap ya, lo que condujo al mismo resultado.

Solo para completar, 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="https://stackoverflow.com/">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"/>
);

En primer lugar, en sus fragmentos no parece que esté envolviendo su código en un Routerpor lo que debes asegurarte de hacerlo por dentro App o en ReactDOM.render:

import { BrowserRouter } from 'react-router-dom';

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>, 
  rootElement
  );

A continuación, su problema específico es que está procesando react-bootstrap Nav.Link en lugar de reaccionar-enrutador Link componente, por lo que el enrutador no detecta los cambios de ruta. Afortunadamente, react-bootstrap proporciona un accesorio de representación en la mayoría de sus componentes para especificar qué componente o elemento desea representar si no desea el valor predeterminado. Cambia a algo como esto:

import { Switch, Route, Link } from 'react-router-dom';

class Navigation extends Component {
  render() {
    return (
      <div>
        <div>
          <Navbar>
            <Navbar.Brand as={Link} to="https://stackoverflow.com/" >React-Bootstrap</Navbar.Brand>
            <Navbar.Collapse>
              <Nav className="mr-auto">
                <NavItem eventkey={1} href="https://stackoverflow.com/">
                  <Nav.Link as={Link} to="https://stackoverflow.com/" >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="https://stackoverflow.com/" component={Home} />
            <Route render={function () {
              return <p>Not found</p>
            }} />
          </Switch>
        </div>
      </div>
    );
  }
}

  • ¡Gracias Señor! el as={Link} y to”…” era lo que me faltaba. Es extraño que los documentos de arranque no mencionen esto en absoluto.

    – mBrice1024

    9 de mayo de 2020 a las 3:41

  • Parece que esto debería haber Nav.Item en lugar de NavItem

    – kugo2006

    20 de octubre de 2020 a las 6:22

  • @kugo2006 Son el mismo componente, pero sí, es una importación menos con Nav.Item. Además, la pregunta era sobre Nav.Link y el enrutador, y parece que acabo de copiar el fragmento de la pregunta de OP y lo arreglé, así que no hice mucha refactorización 🙂

    – Sr. Thompson

    20 oct 2020 a las 22:50

  • Me pregunto dónde puedo encontrar eso en los documentos. Por favor, alguien pegue el enlace a los documentos donde se menciona como referencia. ¿Cómo debemos saber que existe la propiedad ‘como’?

    – Georgi Georgiev

    30 de enero de 2021 a las 13:21

  • @GeorgiGeorgiev reaccionar-bootstrap.github.io/components/navs/#nav-link-props

    – Sr. Thompson

    1 de febrero de 2021 a las 13:27

Avatar de usuario de DedaDev
DedaDev

Para aquellos que tienen un problema con el estilo. Link componente de react-router-dom en la barra de navegación react-bootstrap, simplemente agregue className="nav-link"como esto:

<Link to="/" className="nav-link">Home</Link>

en lugar de

<Nav.Link href="/">Home</Nav.Link>

  • Yo también tuve el mismo problema, pero creo que es mejor usar esto en su lugar: <Nav.Link as={Link} href="/">Home</Nav.Link> dónde {Link} es el componente de react-router-dom.

    – Matías Pizarro

    5 oct 2019 a las 21:06

  • @MatíasP. si usa as={Link} tienes que reemplazar href con to

    – Máx.

    13 de enero de 2020 a las 6:24

  • Gracias. Estas respuestas son exactamente lo que estaba buscando. <Link to="/" className="nav-link">Home</Link> O <Nav.Link as={Link} to="/" >Home</Nav.Link>

    – K. Shaikh

    27 de junio de 2021 a las 12:35


Espero no llegar tarde para ayudar a otras personas que intentan resolver esto.

Puede utilizar NavLink, en lugar de as={Link}. Se renderizará con el mismo comportamiento de Enlace, pero “observará” la URL del enrutador para definir qué enlace está realmente activo:

<Nav defaultActiveKey="/bills" as="ul">
      <Nav.Item as="li">
        <Nav.Link as={NavLink} to="/bills">Dividas</Nav.Link>
      </Nav.Item>
      <Nav.Item as="li">
        <Nav.Link as={NavLink} to="/other">Em construção</Nav.Link>
      </Nav.Item>
    </Nav>

  • Esto no funciona: el tipo ‘”{Link}”‘ no se puede asignar al tipo ‘ElementType | indefinido’. ¿Querías decir ‘”enlace”‘?

    -Richard Barraclough

    15 de abril a las 7:34

Avatar de usuario de Preeti Maurya
Preeti Maurya

import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';

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

y Navbar.js:

import React from 'react';
import {Container,Navbar,Nav,NavItem } from 'react-bootstrap';
import {Link} from 'react-router-dom';

<Nav className="ml-auto">
<NavItem>   <Link className="nav-link"   to="https://stackoverflow.com/">Home</Link> </NavItem> 
<NavItem>   <Link  className="nav-link" to="/about">About</Link> </NavItem> 
<NavItem>    <Link className="nav-link"   to="/contact">Contact</Link> </NavItem> 
</Nav>

Esto resolvió: <Link> fuera de un <Router> error para mi

Actualmente, con react v18 y react-router v6.4, el enfoque que funciona para mí es un poco diferente.

Para hacer que los enlaces funcionen correctamente con el uso de la ruta de reacción as={Link} en el Nav.Link artículo.

Y para resaltar las pestañas, debe usar clave de evento como se describe en la documentación: EventKey se utiliza para determinar y controlar el estado activo del Nav principal

Aquí hay un ejemplo.

Observe que los cambios también afectan a la Navbar.Brand componente.

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

const AppNavbar = () => {
  const location = useLocation();

  const activeKey = location.pathname === "https://stackoverflow.com/" ? '/projects' : location.pathname;

  return (
    <Navbar expand="lg" className="theme-navbar">
      <Container>
        <Navbar.Brand as={Link} to="/">
          My Projects
        </Navbar.Brand>
        <Navbar.Toggle aria-controls="basic-navbar-nav" />
        <Navbar.Collapse id="basic-navbar-nav">
          <Nav activeKey={activeKey} className="me-auto">
            <Nav.Link as={Link} eventKey="/projects" to="/projects">
              Projects
            </Nav.Link>
            <Nav.Link as={Link} eventKey="/work" to="/work">
              Ongoing Tasks
            </Nav.Link>
          </Nav>
        </Navbar.Collapse>
      </Container>
    </Navbar>
  );
};

  • ¡Perfecto! Gracias. Estas api cambian tan rápido que todo lo demás está desactualizado.

    – Árboles4elBosque

    25 de noviembre de 2022 a las 22:23

  • El tipo ‘”{Link}”‘ no se puede asignar al tipo ‘ElementType | indefinido’. ¿Querías decir ‘”enlace”‘?

    -Richard Barraclough

    15 abr a las 7:31

Habiéndome encontrado con un proyecto de tamaño no trivial, y uno que ya tenía jQuery como una dependencia, pude resolver con gracia el desajuste de react-router / react-bootstrap con un detector de eventos en el document.

Esto tiene una ventaja sobre otras soluciones, ya que no requiere cambios en el marcado actual. Sin embargo, es posible que sea necesario escribir alguna lógica adicional que proteja el history.push llamar según necesidades. También es posible que sea necesario ampliar esto para proteger el target atributo, por ejemplo target="_blank".

Si no se desea jQuery, se puede escribir una implementación JS estándar con document.addEventListener sin mucho esfuerzo adicional.

// react-router@5
// usage of history may vary depending on version
import { Router } from 'react-router-dom';
import { createBrowserHistory } from 'history';

const history = createBrowserHistory();

// IIFE scoping jQuery for us
(($) => {
  // Wait for document ready
  $(() => {
    $(document).on('click', '[href]', (event) => {
      // Only target links targeting our application's origin
      if (event.currentTarget.href.indexOf(window.location.origin) === 0) {
        // Prevent standard browser navigation
        event.preventDefault();

        const path = event.currentTarget.href.slice(window.location.origin.length);

        history.push(path);
      }
    });
  });
})(jQuery);

const Routing = (props) => (
  <Router history={ history }>
    ...
  </Router>
);

  • ¡Perfecto! Gracias. Estas api cambian tan rápido que todo lo demás está desactualizado.

    – Árboles4elBosque

    25 de noviembre de 2022 a las 22:23

  • El tipo ‘”{Link}”‘ no se puede asignar al tipo ‘ElementType | indefinido’. ¿Querías decir ‘”enlace”‘?

    -Richard Barraclough

    15 abr a las 7:31

avatar de usuario de ravibagul91
ravibagul91

creo que olvidó incluir bootstrap css, consulte la sección de hojas de estilo del siguiente documento

https://react-bootstrap.github.io/getting-started/introduction/

o simplemente agregue lo siguiente a su index.html

<link
  rel="stylesheet"
  href="https://maxcdn.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css"
  integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS"
  crossorigin="anonymous"
/>

  • Ya incluí bootstrap css en index.js, gracias por la respuesta de todos modos.

    – No es un nombre

    27 de febrero de 2019 a las 20:03

  • no hay nada que ver con css, se trata de reaccionar enrutador

    – Doblador

    28 de febrero de 2019 a las 7:38

¿Ha sido útil esta solución?