history.push() 后组件未呈现
Component is not getting rendered after history.push()
单击按钮后,我通过 history.push()
更改了 URL
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
中传递 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 我看了答案 但他们没有帮助
您每次调用 createHistory()
都会创建新的历史记录。如果您使用 react-router-dom
,您可以简单地使用 withRouter
HOC,它将通过 prop
向组件提供 history
对象。然后,您将使用 history.push('/')
,或者如果它位于 class component
、this.props.history.push('/')
等等。
工作示例:https://codesandbox.io/s/p694ln9j0
routes(在routes
内定义history
)
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
,因为像[=这样的组件30=] 不在 <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(在自己的文件中定义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(仍然知道路由并且已经通过 <Route path="/" component={Home} />
HOC 传入了 history
对象,所以导入 history
不是必需的,但如果您愿意,您仍然可以导入它——只是不要在 Home
的函数参数中解构 history
)
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>
);
几点:
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;
您必须通过 npm install --save react-history
安装 react-history
软件包
3) 将 history 导入主文件并将其传递到 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>
)
}
}
希望对您有所帮助..
:)
使用 import { Router }
而不是 import { BrowserRouter as Router }
。
因为 BrowserRouter 忽略了 history prop.
这可能对某人有所帮助。确保 history
包版本与 react-router-dom
.
兼容
这个组合没有对我有用:
历史:5.0.0
与 react-router-dom:5.2.0
这个组合做了:
历史:4.10.1
和 react-router-dom 5.2.0
检查 react 版本, react-router, react-router-dom 和 history package 版本也是无能为力 –
我的配置 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"
检查这个 link :-
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
对于 使用钩子的人,使用 useLocation()
钩子而不是 useHistory()
有效。
const { pathname } = useLocation();
每次路径名更改时组件都会重新呈现。
将历史包降级为历史:4.10.1 with react-router-dom 5.2.0 对我有用
使用这个:
import { useHistory, useRouteMatch } from 'react-router-dom';
let history = useHistory();
let match = useRouteMatch();
单击按钮后,我通过 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
中传递 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 我看了答案
您每次调用 createHistory()
都会创建新的历史记录。如果您使用 react-router-dom
,您可以简单地使用 withRouter
HOC,它将通过 prop
向组件提供 history
对象。然后,您将使用 history.push('/')
,或者如果它位于 class component
、this.props.history.push('/')
等等。
工作示例:https://codesandbox.io/s/p694ln9j0
routes(在routes
内定义history
)
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
,因为像[=这样的组件30=] 不在 <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(在自己的文件中定义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(仍然知道路由并且已经通过 <Route path="/" component={Home} />
HOC 传入了 history
对象,所以导入 history
不是必需的,但如果您愿意,您仍然可以导入它——只是不要在 Home
的函数参数中解构 history
)
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>
);
几点:
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;
您必须通过 npm install --save react-history
react-history
软件包
3) 将 history 导入主文件并将其传递到 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>
)
}
}
希望对您有所帮助..
:)
使用 import { Router }
而不是 import { BrowserRouter as Router }
。
因为 BrowserRouter 忽略了 history prop.
这可能对某人有所帮助。确保 history
包版本与 react-router-dom
.
这个组合没有对我有用:
历史:5.0.0
与 react-router-dom:5.2.0
这个组合做了:
历史:4.10.1
和 react-router-dom 5.2.0
检查 react 版本, react-router, react-router-dom 和 history package 版本也是无能为力 – 我的配置 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"
检查这个 link :- 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
对于 使用钩子的人,使用 useLocation()
钩子而不是 useHistory()
有效。
const { pathname } = useLocation();
每次路径名更改时组件都会重新呈现。
将历史包降级为历史:4.10.1 with react-router-dom 5.2.0 对我有用
使用这个:
import { useHistory, useRouteMatch } from 'react-router-dom';
let history = useHistory();
let match = useRouteMatch();