- 首页
- 其他开发
- 组件在 history.push() 之后没有被渲染
组件在 history.push() 之后没有被渲染
[英] Component is not getting rendered after history.push()
本文介绍了组件在 history.push() 之后没有被渲染的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
在单击按钮时,我通过执行 history.push()
来更改 URL
从'history/createBrowserHistory'导入createHistoryconst 历史 = createHistory()..一些代码.history.push(`/share/${objectId}`)
并希望该 URL 的 Route
中提到的组件能够呈现,但这并没有发生.但是,在刷新该组件时会按预期呈现.但我不明白为什么它不会在 URL 更改时立即呈现.我尝试将组件包装在 withRouter
中.
import React, {Component} from 'react'从react-router-dom"导入 {BrowserRouter, Router, Route, Switch, withRouter}从'history/createBrowserHistory'导入createHistory从./pages/home"导入主页从 './pages/view-file' 导入 ViewFileconst 历史 = createHistory()类 App 扩展组件 {构造函数(道具){超级(道具)}使成为() {返回 (<浏览器路由器><开关><路由精确路径={'/'} component={Home}/><Route path={'/share/:id'} component={withRouter(ViewFile)}/></开关></BrowserRouter>)}}导出默认应用
以及在 Router
中传递 history 我认为这与使用 BrowserRouter
相同.
import React, {Component} from 'react'从react-router-dom"导入 {BrowserRouter, Router, Route, Switch, withRouter}从'history/createBrowserHistory'导入createHistory从./pages/home"导入主页从 './pages/view-file' 导入 ViewFileconst 历史 = createHistory()类 App 扩展组件 {构造函数(道具){超级(道具)}使成为() {返回 (<路由器历史={历史}><开关><路由精确路径={'/'} component={Home}/><Route path={'/share/:id'} component={ViewFile}/></开关></路由器>)}}导出默认应用
但没有得到任何运气.谁能解释为什么会这样?
PS 我浏览了答案 这里 但他们没有帮助
解决方案
每次调用 createHistory()
时,都会创建新的历史记录.如果您使用 react-router-dom
,您可以简单地使用 withRouter
HOC,它将通过一个组件提供 history
对象道具
.然后,您将使用 history.push('/')
,或者如果它在 类组件
中,this.props.history.push('/')
等等.
工作示例:https://codesandbox.io/s/p694ln9j0
路由(在routes
中定义history
)
从react"导入React;从react-router-dom"导入{路由器,路由,交换机};从历史"导入 { createBrowserHistory };从../components/Header"导入标题;从../components/Home"导入Home;从../components/About"导入关于;从../components/Contact"导入联系人;从../components/ScrollIntoView"导入 ScrollIntoView;const 历史 = createBrowserHistory();导出默认值 () =>(<路由器历史={历史}><div><ScrollIntoView><标题/><开关><路由精确路径="/" component={Home}/><Route path="/about" component={About}/><Route path="/contact" component={Contact}/></开关><标题/></ScrollIntoView>
</路由器>);
components/Header.js(我们想访问history
,然而,有时我们不得不使用withRouter
,因为像这样的组件Header
不在 <Route "/example" component={Header}/>
HOC 中,所以它不知道我们的路由)
从react"导入React;import { withRouter } from "react-router-dom";const Header = ({ history }) =>(<标题><nav style={{ textAlign: "center" }}><ul style={{ listStyleType: "none" }}><li style={{ display: "inline", marginRight: 20 }}><button onClick={() =>history.push("/")}>Home</button><li style={{ display: "inline", marginRight: 20 }}><button onClick={() =>history.push("/about")}>关于</button><li style={{ display: "inline", marginRight: 20 }}><button onClick={() =>history.push("/contact")}>联系方式</button></nav></标题>);导出默认 withRouter(Header);
components/Home.js(像 Home
这样的组件知道路由并且已经通过 history
对象传入><Route path="/" component={Home}/> HOC,所以 withRouter
不是必需的)
从react"导入React;const Home = ({历史}) =>(<div className="容器"><按钮className="英国按钮英国按钮危险"onClick={() =>history.push("/notfound")}>未找到按钮><p>...</p>
);导出默认首页;
<小时>
与上述相同的概念,但是,如果您不想使用 withRouter
,那么您可以简单地创建一个将在您的组件之间共享的 history
实例需要它.您将import
这个history
实例并使用history.push('/');
等进行导航.
工作示例:https://codesandbox.io/s/5ymj657k1k
history(在自己的文件中定义history
)
import { createBrowserHistory } from "history";const 历史 = createBrowserHistory();导出默认历史记录;
路由(将history
导入routes
)
从react"导入React;从react-router-dom"导入{路由器,路由,交换机};从../components/Header"导入标题;从../components/Home"导入Home;从../components/About"导入关于;从../components/Contact"导入联系人;从../components/ScrollIntoView"导入 ScrollIntoView;从../history"导入历史;导出默认值 () =>(<路由器历史={历史}><div><ScrollIntoView><标题/><开关><路由精确路径="/" component={Home}/><Route path="/about" component={About}/><Route path="/contact" component={Contact}/></开关><标题/></ScrollIntoView>
</路由器>);
components/Header.js(将history
导入Header
)
从react"导入React;从../history"导入历史;const 标题 = () =>(<标题><nav style={{ textAlign: "center" }}><ul style={{ listStyleType: "none" }}><li style={{ display: "inline", marginRight: 20 }}><button onClick={() =>history.push("/")}>Home</button><li style={{ display: "inline", marginRight: 20 }}><button onClick={() =>history.push("/about")}>关于</button><li style={{ display: "inline", marginRight: 20 }}><button onClick={() =>history.push("/contact")}>联系方式</button></nav></标题>);导出默认标题;
components/Home.js(仍然知道路由并且已经通过 <Route path="/" 组件传入了 history
对象={Home}/>
HOC,因此不需要导入 history
,但是如果您愿意,您仍然可以导入它——只是不要解构 history
在Home
的函数参数中)
从react"导入React;const Home = ({历史}) =>(<div className="容器"><按钮className="英国按钮英国按钮危险"onClick={() =>history.push("/notfound")}>未找到按钮><p>...</p>
);导出默认首页;
<小时>
但您可能会想,BrowserRouter
怎么样?好吧,BrowserRouter
有它自己的内部 history
对象.我们可以再次使用withRouter
来访问它的history
.在这种情况下,我们甚至根本不需要createHistory()
!
工作示例:https://codesandbox.io/s/ko8pkzvx0o
路线
从react"导入React;从react-router-dom"导入 { BrowserRouter, Route, Switch };从../components/Header"导入标题;从../components/Home"导入Home;从../components/About"导入关于;从../components/Contact"导入联系人;从../components/Notfound"导入 Notfound;从../components/ScrollIntoView"导入 ScrollIntoView;导出默认值 () =>(<浏览器路由器><div><ScrollIntoView><标题/><开关><路由精确路径="/" component={Home}/><Route path="/about" component={About}/><Route path="/contact" component={Contact}/><路由组件={Notfound}/></开关><标题/></ScrollIntoView>
</BrowserRouter>);
On a button click, I am getting the URL changed by doing history.push()
import createHistory from 'history/createBrowserHistory'
const history = createHistory()
.
. some code
.
history.push(`/share/${objectId}`)
and hoping the component mentioned in the Route
for that URL would render but that is not happening. Though, on refreshing that component is getting rendered as expected. But I don't get that why it is not rendering as soon as the URL is changing. I've tried wrapping the component inside 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
as well as passing history in Router
which I think same as using 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
but not getting any luck with this. Can anyone explain why is this happening?
P.S I went through the answers here but they didn't help
解决方案
You're creating new history each time you invoke createHistory()
. If you're using react-router-dom
you can simply use the withRouter
HOC that'll supply the history
object to the component via a prop
. You'll then utilize history.push('/')
, or if it's in a class component
, this.props.history.push('/')
and so on.
Working example: https://codesandbox.io/s/p694ln9j0
routes (define history
within 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 (we want to access history
, however, sometimes we have to use withRouter
because components like Header
don't reside within a <Route "/example" component={Header}/>
HOC, so it's unaware of our routing)
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 (a component like Home
is aware of routing and has the history
object already passed in via the <Route path="/" component={Home} />
HOC, so withRouter
isn't required)
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;
Same concept as above, however, if you don't want to use withRouter
, then you can simply create a history
instance that'll be shared across your components that need it. You'll import
this history
instance and navigate with history.push('/');
and so on.
Working example: https://codesandbox.io/s/5ymj657k1k
history (define history
in its own file)
import { createBrowserHistory } from "history";
const history = createBrowserHistory();
export default history;
routes (import history
into 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 (import history
into 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 (is still aware of routing and has the history
object already passed in via the <Route path="/" component={Home} />
HOC, so importing history
isn't required, but you can still import it if you wanted to -- just don't deconstruct history
in the Home
's function parameters)
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;
But you might be thinking, what about BrowserRouter
? Well, BrowserRouter
has it's own internal history
object. We can, once again, use withRouter
to access its history
. In this case, we don't even need to createHistory()
at all!
Working example: https://codesandbox.io/s/ko8pkzvx0o
routes
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>
);
这篇关于组件在 history.push() 之后没有被渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!