Компонент не отображается после history.push()

При нажатии кнопки я получаю изменение URL-адреса, выполняя history.push()

import createHistory from 'history/createBrowserHistory'  
const history = createHistory()  
.  
. some code  
.  
history.push(`/share/${objectId}`)

и надеясь, что компонент, упомянутый в Route для этого URL-адреса, отобразится, но этого не происходит. Однако при обновлении этот компонент отображается, как и ожидалось. Но я не понимаю, почему он не отображается, как только URL-адрес меняется. Я пробовал завернуть компонент внутрь withRouter.

import React, {Component} from 'react'  
import {BrowserRouter, Router, Route, Switch, withRouter} from 'react-router-dom'  
import createHistory from 'history/createBrowserHistory'  

import Home from './pages/home'  
import ViewFile from './pages/view-file'  

const history = createHistory()

class App extends Component {
    constructor(props) {
      super(props)
    }

      render() {
      return (
          <BrowserRouter>
              <Switch>
                  <Route exact path = {'/'} component = {Home}/>
                  <Route path = {'/share/:id'} component = {withRouter(ViewFile)}/>
              </Switch>
          </BrowserRouter>
      )
  }
}

export default App 

а также передать история в Router, что я думаю так же, как использовать BrowserRouter.

import React, {Component} from 'react'  
import {BrowserRouter, Router, Route, Switch, withRouter} from 'react-router-dom'  
import createHistory from 'history/createBrowserHistory'  

import Home from './pages/home'  
import ViewFile from './pages/view-file'  

const history = createHistory()

class App extends Component {
    constructor(props) {
      super(props)
    }

      render() {
      return (
          <Router history = {history}>
              <Switch>
                  <Route exact path = {'/'} component = {Home}/>
                  <Route path = {'/share/:id'} component = {ViewFile}/>
              </Switch>
          </Router>
      )
  }
}

export default App 

но с этим не повезло. Кто-нибудь может объяснить, почему это происходит?
P.S Просмотрел ответы здесь но они не помогли

Можете ли вы вставить больше кода, касающегося места, где вы звоните: history.push(/share/${objectId})

James Delaney 12.03.2019 22:33

какая версия реактивного маршрутизатора?

Sujit.Warrier 13.03.2019 03:09

@Sujit.WarrierIt 4.3.1

Neeraj Sewani 13.03.2019 06:54
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
10
4
21 880
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

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

Вы создаете новую историю каждый раз, когда вызываете createHistory(). Если вы используете react-router-dom, вы можете просто использовать withRouter HOC, который будет передавать объект history компоненту через prop. Затем вы будете использовать history.push('/') или, если он находится в class component, this.props.history.push('/') и так далее.

Рабочий пример: https://codesandbox.io/s/p694ln9j0

маршруты (определить history внутри routes)

import React from "react";
import { Router, Route, Switch } from "react-router-dom";
import { createBrowserHistory } from "history";
import Header from "../components/Header";
import Home from "../components/Home";
import About from "../components/About";
import Contact from "../components/Contact";
import ScrollIntoView from "../components/ScrollIntoView";

const history = createBrowserHistory();

export default () => (
  <Router history = {history}>
    <div>
      <ScrollIntoView>
        <Header />
        <Switch>
          <Route exact path = "/" component = {Home} />
          <Route path = "/about" component = {About} />
          <Route path = "/contact" component = {Contact} />
        </Switch>
        <Header />
      </ScrollIntoView>
    </div>
  </Router>
);

компоненты/Header.js (мы хотим получить доступ к history, однако иногда нам приходится использовать withRouter, потому что такие компоненты, как Header, не находятся в <Route "/example" component = {Header}/> HOC, поэтому он не знает о нашей маршрутизации)

import React from "react";
import { withRouter } from "react-router-dom";

const Header = ({ history }) => (
  <header>
    <nav style = {{ textAlign: "center" }}>
      <ul style = {{ listStyleType: "none" }}>
        <li style = {{ display: "inline", marginRight: 20 }}>
          <button onClick = {() => history.push("/")}>Home</button>
        </li>
        <li style = {{ display: "inline", marginRight: 20 }}>
          <button onClick = {() => history.push("/about")}>About</button>
        </li>
        <li style = {{ display: "inline", marginRight: 20 }}>
          <button onClick = {() => history.push("/contact")}>Contact</button>
        </li>
      </ul>
    </nav>
  </header>
);

export default withRouter(Header);

компоненты/Home.js (такой компонент, как Home, знает о маршрутизации и имеет объект history, уже переданный через <Route path = "/" component = {Home} /> HOC, поэтому withRouter не требуется)

import React from "react";

const Home = ({ history }) => (
  <div className = "container">
    <button
      className = "uk-button uk-button-danger"
      onClick = {() => history.push("/notfound")}
    >
      Not Found
    </button>
    <p>
      ...
    </p>
  </div>
);

export default Home;

Та же концепция, что и выше, однако, если вы не хотите использовать withRouter, вы можете просто создать экземпляр history, который будет использоваться всеми вашими компонентами, которым он нужен. Вы будете import этот history экземпляр и будете перемещаться с помощью history.push('/'); и так далее.

Рабочий пример: https://codesandbox.io/s/5ymj657k1k

история (определить history в собственном файле)

import { createBrowserHistory } from "history";

const history = createBrowserHistory();

export default history;

маршруты (импортировать history в routes)

import React from "react";
import { Router, Route, Switch } from "react-router-dom";
import Header from "../components/Header";
import Home from "../components/Home";
import About from "../components/About";
import Contact from "../components/Contact";
import ScrollIntoView from "../components/ScrollIntoView";
import history from "../history";

export default () => (
  <Router history = {history}>
    <div>
      <ScrollIntoView>
        <Header />
        <Switch>
          <Route exact path = "/" component = {Home} />
          <Route path = "/about" component = {About} />
          <Route path = "/contact" component = {Contact} />
        </Switch>
        <Header />
      </ScrollIntoView>
    </div>
  </Router>
);

компоненты/Header.js (импортировать history в Header)

import React from "react";
import history from "../history";

const Header = () => (
  <header>
    <nav style = {{ textAlign: "center" }}>
      <ul style = {{ listStyleType: "none" }}>
        <li style = {{ display: "inline", marginRight: 20 }}>
          <button onClick = {() => history.push("/")}>Home</button>
        </li>
        <li style = {{ display: "inline", marginRight: 20 }}>
          <button onClick = {() => history.push("/about")}>About</button>
        </li>
        <li style = {{ display: "inline", marginRight: 20 }}>
          <button onClick = {() => history.push("/contact")}>Contact</button>
        </li>
      </ul>
    </nav>
  </header>
);

export default Header;

компоненты/Home.js (по-прежнему знает о маршрутизации и имеет объект history, уже переданный через <Route path = "/" component = {Home} /> HOC, поэтому импорт history не требуется, но вы все равно можете импортировать его, если хотите — просто не разбирайте history в Home' параметры функции)

import React from "react";

const Home = ({ history }) => (
  <div className = "container">
    <button
      className = "uk-button uk-button-danger"
      onClick = {() => history.push("/notfound")}
    >
      Not Found
    </button>
    <p>
      ...
    </p>
  </div>
);

export default Home;

Но вы можете подумать, а как насчет BrowserRouter? Ну, у BrowserRouter есть свой внутренний history объект. Мы снова можем использовать withRouter для доступа к его history. В этом случае нам даже не нужно createHistory() вообще!

Рабочий пример: https://codesandbox.io/s/ko8pkzvx0o

маршруты

import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import Header from "../components/Header";
import Home from "../components/Home";
import About from "../components/About";
import Contact from "../components/Contact";
import Notfound from "../components/Notfound";
import ScrollIntoView from "../components/ScrollIntoView";

export default () => (
  <BrowserRouter>
    <div>
      <ScrollIntoView>
        <Header />
        <Switch>
          <Route exact path = "/" component = {Home} />
          <Route path = "/about" component = {About} />
          <Route path = "/contact" component = {Contact} />
          <Route component = {Notfound} />
        </Switch>
        <Header />
      </ScrollIntoView>
    </div>
  </BrowserRouter>
);

Большое спасибо. Вчера я потратил часы на чтение документации по реактивному маршрутизатору, но мало что понял. Я думаю, вы должны были написать документы.

Neeraj Sewani 13.03.2019 11:28

Это не работает, я понятия не имею, почему, я использую Router, а не BrowserRouter, но все мои компоненты не отображаются, URL-адрес меняется, но я всегда получаю компонент резервного маршрута 404.

Hassan Azzam 07.07.2020 22:11

@HassanAzzam Создайте MCVE, а затем задать новый вопрос с вашим примером кода.

Matt Carlotta 07.07.2020 22:47

Это точно такой же код выше, и он не работает, я даже пробовал history.listen, и он возвращает undefined, когда я меняю маршруты.

Hassan Azzam 07.07.2020 22:49

@HassanAzzam Похоже, они отказались от поддержки использования вашего собственного объекта истории в v5. Когда это было написано, v4.x.x была последней, и поэтому она работает как ожидал. Я бы посоветовал вам отказаться от этого подхода, так как есть другие лучшие альтернативы (например, использование BrowserRouter либо с хуком useHistory, либо доступ к history с помощью компонента более высокого порядка withRouter, если вы не используете хуки).

Matt Carlotta 07.07.2020 23:28

Или... если вы используете redux, то используйте подключенный реактивный маршрутизатор, что позволяет вам push или replace элементы в истории из любого места.

Matt Carlotta 07.07.2020 23:33

Да, я знаю, но проблема в том, что я хотел использовать его вне компонента, а useHistory работает только внутри компонента. Но в любом случае спасибо за разъяснение, вы сэкономили мне много времени.

Hassan Azzam 07.07.2020 23:42

проверьте версию react , react-router, react-router-dom и версию пакета истории, которая также бессильна

AmitNayek 04.02.2021 19:02

Я просто удивляюсь, почему эти вещи не стандартизированы. Почему всем приходится бороться.

prashantsahni 22.12.2021 05:03

Несколько моментов:

1) Используйте import { Router} from 'react-router-dom' вместо import { BrowserRouter as Router} from 'react-router-dom'

2) Создайте переменную history в другом файле, а именно (можно изменить) ../src/services/history.js и содержание должно быть:

import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
export default history;

Вам нужно будет установить пакет react-history до npm install --save react-history

3) Импортируйте историю в основной файл и передайте ее внутри компонента Router.

import React from 'react';
import { Router, Route, Switch } from 'react-router-dom'
import history from './services/history'


class App extends React.Component {

    render() {
        return (
            <Router history = {history}>
                <Switch>
                    <Route exact path='/' component = {MainPage}></Route>
                    <Route exact path='/vendor' component = {VendorPage}></Route>
                    <Route exact path='/client' component = {ClientPage}></Route>
                </Switch>
            </Router>
        );
    }
}

export default App;

4) Теперь вы можете использовать history в любом месте компонентов,

import React from 'react'
import history from '../services/history';

export default class VendorPage extends React.Component {

    loginUser = () => {
        if (<SOME_CONDITION>)
            history.push('/client')
    }

    render() {
        return (
            <h1>Welcome to Vendor Page....</h1>
        )
    }
}

Надеюсь, поможет..

:)

Я думаю, что он может useHistory() крючок react-router-dom, так что ему не придется устанавливать другую библиотеку.

Rhaidzsal Ali 11.12.2019 08:52

к сожалению, это больше не работает

HellBaby 04.11.2020 10:12

Это не работает ожидаемым образом для react-router-dom v6

Tanishq Vyas 30.11.2021 11:24

используйте import { Router } вместо import { BrowserRouter as Router } . Поскольку BrowserRouter игнорирует реквизит истории.

Ух ты! Вот оно! Столько часов пытался найти это! history.push() точно так же работает с Router.

Alexis Wilke 17.12.2020 06:31

Вау, это проще, чем я думал. Спасибо!

Brandon Austin 02.03.2021 19:51

Установка BrowserRouter prod forceRefresh на true также работает. <BrowserRouter forceRefresh = {true}>

Nabarun 28.06.2021 15:02

Это может кому-то помочь. Убедитесь, что версия пакета history совместима с версией react-router-dom.

Эта комбинация не работает для меня:

история: 5.0.0 с реактивным роутером: 5.2.0

Это комбо сделал:

история: 4.10.1 с реактивным роутером 5.2.0

Спасибо! Я была такая же проблема.

Denys Kotsur 26.01.2021 17:58

+1 это сработало для меня. У меня была история в v 5.0.0 и точно такой же react-router-dom в 5.2.0!!! Спасибо! Спас мой день ;)

Rafath 26.03.2021 14:47

Большое спасибо! Целый день искал этот ответ!!!

jvbs 27.06.2021 01:49

Спасибо! Оно работало завораживающе

behzad 19.01.2022 17:00

проверить версию react, react-router, react-router-dom и версию пакета history, которая также бесполезна – моя конфигурация package.json

"history": "^4.10.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-router": "5.1.2",
"react-router-dom": "5.1.2"

проверьте эту ссылку: - https://stackblitz.com/edit/react-34ohqv?embed=1&file=package.jsonhttps://stackblitz.com/edit/react-router-example-mahi-hzitgg?embed=1&file=index.js

Потратил 3 часа на то, почему история не работала, вот в чем причина. Спасибо!

Brad Vanderbush 28.04.2021 04:13

Точно!!! Почему-то версия истории 5 не работает! Когда я понизил версию до предложенной версии, все работало нормально. Спасибо!

jNewbie 02.09.2021 04:29

Для люди, использующие хуки сработало использование хука useLocation() вместо useHistory().

  const { pathname } = useLocation();

Компонент перерисовывается каждый раз, когда изменяется путь.

Понижение пакета истории до истории: у меня работает 4.10.1 с react-router-dom 5.2.0

Использовать этот:

import { useHistory, useRouteMatch } from 'react-router-dom';

let history = useHistory();
let match = useRouteMatch();

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