在history.push()之后未呈现组件

时间:2019-03-12 20:47:02

标签: reactjs react-router browser-history history.js

单击按钮后,我通过执行history.push()

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

,并希望该URL的Route中提到的组件可以呈现,但不会发生。但是,在刷新时,该组件正按预期方式呈现。但是我不明白为什么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中传递 history ,我认为这与使用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我回答了here,但他们没有帮助

8 个答案:

答案 0 :(得分:5)

使用import { Router }代替import { BrowserRouter as Router }。 因为BrowserRouter会忽略历史记录道具。

答案 1 :(得分:2)

检查 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.json https://stackblitz.com/edit/react-router-example-mahi-hzitgg?embed=1&file=index.js

答案 2 :(得分:1)

您每次调用createHistory()时都在创建新的历史记录。如果您使用的是react-router-dom,则可以简单地使用withRouter HOC,它将通过history向组件提供prop对象。然后,您将利用history.push('/'),或者如果它在class componentthis.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 HOC传递了<Route path="/" component={Home} />对象,因此不需要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>
);

components / 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 HOC传递了<Route path="/" component={Home} />对象,因此导入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>
);

答案 3 :(得分:1)

将历史包降级为历史:4.10.1 with react-router-dom 5.2.0 对我有用

答案 4 :(得分:0)

几点:

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)将历史记录导入主文件,并将其传递到路由器组件内部。

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

希望对您有帮助。

:)

答案 5 :(得分:0)

这可能会帮助某人。确保history软件包版本与react-router-dom兼容。

此组合没有对我有用:

历史记录:5.0.0,带有react-router-dom:5.2.0

此组合完成

历史记录:4.10.1,带有react-router-dom 5.2.0

答案 6 :(得分:0)

对于使用钩子的人,使用 useLocation() 钩子代替 useHistory() 有效。

  const { pathname } = useLocation();

每次路径名更改时组件都会重新渲染。

答案 7 :(得分:0)

使用这个:

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

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