ReactJS Bootstrap Navbar и маршрутизация не работают вместе

Я пытаюсь создать простое веб-приложение, используя ReactJS, и я хотел использовать Navbar, предоставляемый React-Bootstrap.

Я создал файл Navigation.js, содержащий класс Navigation, чтобы отделить Navbar и маршрутизацию от файла App.js. Однако обе части, похоже, не работают. Когда я загружаю страницу, она просто пуста, навбара нет. Кто-нибудь может заметить ошибку?

Навигация.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;

Я пытался использовать NavItem, уже содержащий LinkContainer из react-router-bootstrap, что привело к тому же результату.

Просто для полноты, 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"/>
);
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
51
0
48 951
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Прежде всего, в ваших фрагментах кода не похоже, что вы заключаете свой код в Router, поэтому вы должны убедиться, что вы делаете это внутри App или в ReactDOM.render:

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

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

Далее, ваша конкретная проблема заключается в том, что вы визуализируете компонент Nav.Link реакции-загрузки вместо компонента Link реакции-маршрутизатора, поэтому маршрутизатор не улавливает изменения вашего маршрута. К счастью, react-bootstrap предоставляет поддержку рендеринга в большинстве своих компонентов, чтобы указать, какой компонент или элемент вы хотите визуализировать, если вы не хотите использовать значение по умолчанию. Переключитесь на что-то вроде этого:

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>
    );
  }
}

Спасибо, сэр! as = {Link} и to"..." было тем, чего мне не хватало. Странно, что документы начальной загрузки вообще не упоминают об этом.

mBrice1024 09.05.2020 05:41

Похоже, здесь должно быть Nav.Item вместо NavItem

kugo2006 20.10.2020 08:22

@ kugo2006 Это один и тот же компонент, но да, с Nav.Item на один импорт меньше. Кроме того, вопрос был о Nav.Link и маршрутизаторе, и похоже, что я просто скопировал фрагмент из вопроса ОП и исправил его, поэтому я не делал много рефакторинга :)

SrThompson 21.10.2020 00:50

Мне интересно, где я могу найти это в документах. Пожалуйста, кто-нибудь вставьте ссылку на документы, где это упоминается для справки. Откуда нам знать, что существует свойство «как»?

Georgi Georgiev 30.01.2021 14:21

@GeorgiGeorgiev реакция-bootstrap.github.io/components/navs/#nav-link-props

SrThompson 01.02.2021 14:27

я думаю, вы забыли включить bootstrap css, обратитесь к разделу таблиц стилей следующего документа

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

или просто добавьте следующее в ваш index.html

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

Я уже включил bootstrap css в index.js, в любом случае спасибо за ответ.

NotAName 27.02.2019 21:03

здесь нет ничего общего с css, речь идет о реагирующем маршрутизаторе

Bender 28.02.2019 08:38

Для тех, у кого есть проблемы со стилем компонента Link из react-router-dom в панели навигации react-bootstrap, просто добавьте className = "nav-link", например так:

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

вместо

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

У меня тоже была такая же проблема, но я думаю, что вместо этого лучше использовать это: <Nav.Link as = {Link} href = "/">Home</Nav.Link>, где {Link} — компонент из react-router-dom.

Matías Pizarro 05.10.2019 23:06

@МатиасП. Если вы используете as = {Link}, вы должны заменить href на to

Kiran P. 13.01.2020 07:24

Спасибо. Эти ответы именно то, что я искал <Link to = "/" className = "nav-link">Home</Link> ИЛИ <Nav.Link as = {Link} to = "/" >Home</Nav.Link>

K. Shaikh 27.06.2021 14:35
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';

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

и 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 = "/">Home</Link> </NavItem> 
<NavItem>   <Link  className = "nav-link" to = "/about">About</Link> </NavItem> 
<NavItem>    <Link className = "nav-link"   to = "/contact">Contact</Link> </NavItem> 
</Nav>

Это устранило: <Link> за пределами <Router> ошибки для меня.

Обнаружив, что у меня есть проект нетривиального размера, который уже имел jQuery в качестве зависимости, я смог изящно решить несоответствие react-router/react-bootstrap с прослушивателем событий на document.

У этого есть одно преимущество перед другими решениями, заключающееся в том, что оно не требует изменения текущей разметки. Однако может потребоваться написать дополнительную логику, защищающую вызов history.push, в зависимости от потребностей. Также может потребоваться расширить это, чтобы защитить атрибут target, например. target = "_blank".

Если jQuery не нужен, можно написать ванильную реализацию JS с помощью document.addEventListener без особых дополнительных усилий.

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

Надеюсь, я не опоздал, чтобы помочь другим людям, пытающимся решить эту проблему.

Вы можете использовать NavLink вместо as = {Link}. Он будет отображаться с тем же поведением, что и Link, но будет «следить» за URL-адресом маршрутизатора, чтобы определить, какая ссылка действительно активна:

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

Другие вопросы по теме