Компонент не отображается после history.push () - PullRequest
0 голосов
/ 12 марта 2019

При нажатии кнопки я получаю измененный 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 Я прошел ответы здесь , но они не помогли

1 Ответ

1 голос
/ 13 марта 2019

Вы создаете новую историю каждый раз, когда вызываете 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>
);

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

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

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