组件在 history.push() 之后没有被渲染 [英] Component is not getting rendered after history.push()

查看:35
本文介绍了组件在 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,但是如果您愿意,您仍然可以导入它——只是不要解构 historyHome的函数参数中)

从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屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆