【问题标题】:history.push changes url, but component is not renderedhistory.push 改变了 url,但是组件没有被渲染
【发布时间】:2021-08-09 04:28:43
【问题描述】:

为什么history.push("/dashboard")将url改成/dashboardDashboard组件没有渲染?

Gif showcasing the issue,如你所见,我必须手动点击刷新按钮才能触发重新渲染。


index.js

import ReactDOM from "react-dom";

import Router from "./Router";

const rootElement = document.getElementById("root");
ReactDOM.render(
    <Router />,
  rootElement
);

LoginForm.js

import React, {Component} from "react"

class LoginForm extends Component {

    handleSubmit = (event) => {
    event.preventDefault()
    this.props.history.push("/dashboard")
    }

    render() {
        return (
                <form name="signup_form" onSubmit={this.handleSubmit}>
                    <input type="submit" value="Sign Up"/>
                </form>
        )
    }

}

export default LoginForm

Router.js

import LoginForm from "./LoginForm";
import {BrowserRouter, Route, Switch } from "react-router-dom";
import React, {Component} from "react";
import { createBrowserHistory } from "history"

const browserHistory = createBrowserHistory()

class Router extends Component {

    render() {
        return (
                <BrowserRouter >
                    <LoginForm history={browserHistory} />
                    <Switch>
                        <Route path="/dashboard" component={Dashboard}/>
                    </Switch>
                </BrowserRouter>
        )
    }
}
export default Router

function Dashboard() {
  return <h1>Dashboard</h1>
}

【问题讨论】:

  • 请将App 组件添加到您的代码框
  • 我收到一个错误,因为没有 App.js 文件
  • edit : 现在没有错误了,但是你必须添加你的代码

标签: reactjs react-router react-router-dom history


【解决方案1】:

问题

您正在创建一个您的BrowserRouter 不知道的自定义历史对象。 LoginForm 组件正在操作 history 对象的一个​​版本,而路由器和路由正在使用路由上下文使用的默认 history 对象。登录表单能够更新地址栏中的 URL,但外部路由上下文无法看到此更改。

解决方案

要么删除自定义历史记录并使用BrowsserRouter 提供的历史记录,要么使用较低级别的Router 组件并将自定义history 对象传递给它以在路由上下文中使用。

使用路由上下文中的标准历史记录

Router.js

<BrowserRouter >
  <LoginForm/>
  <Switch>
    <Route path="/dashboard" component={Dashboard}/>
  </Switch>
</BrowserRouter>

LoginForm - 使用 withRouter 高阶组件进行装饰,以便它从最近的路由上下文接收路由道具。

import React, {Component} from "react";
import { withRouter } from 'react-router-dom';

class LoginForm extends Component {

  handleSubmit = (event) => {
    event.preventDefault()
    this.props.history.push("/dashboard")
  }

  render() {
    return (
      <form name="signup_form" onSubmit={this.handleSubmit}>
        <input type="submit" value="Sign Up"/>
      </form>
    );
  }

}

export default withRouter(LoginForm);

使用自定义历史记录

import LoginForm from "./LoginForm";
import { Router, Route, Switch } from "react-router-dom";
import React, { Component } from "react";
import { createBrowserHistory } from "history"

const browserHistory = createBrowserHistory()

class MyRouter extends Component {
  render() {
    return (
      <Router history={browserHistory} >
        <LoginForm />
        <Switch>
          <Route path="/dashboard" component={Dashboard}/>
        </Switch>
      </Router>
    )
  }
}
export default MyRouter;

并且仍然使用withRouter HOC 装饰LoginForm,以便通过路由道具。

import React, {Component} from "react";
import { withRouter } from 'react-router-dom';

class LoginForm extends Component {

  handleSubmit = (event) => {
    event.preventDefault()
    this.props.history.push("/dashboard")
  }

  render() {
    return (
      <form name="signup_form" onSubmit={this.handleSubmit}>
        <input type="submit" value="Sign Up"/>
      </form>
    );
  }

}

export default withRouter(LoginForm);

建议

正如所写,LoginForm 组件将总是被渲染,这可能不是您想要的。我建议只是将它移动到一条路线中,以便通过路线道具。

<Route path="/login" component={LoginForm} />

【讨论】:

    【解决方案2】:

    请更换路由器。如果你这样写,LoginForm 将始终呈现。

    import {BrowserRouter, Route, Switch } from "react-router-dom";
    import React, {Component} from "react";
    import { createBrowserHistory } from "history"
    
    class Routers extends Component {
        render() {
            return (
                    <BrowserRouter>
                        <Switch>
                            <Route path="/login" component={LoginForm}/>
                            <Route path="/dashboard" component={Dashboard}/>
                        </Switch>
                    </BrowserRouter>
            )
        }
    }
    
    

    【讨论】:

    • 它似乎不起作用......你能解释一下将 BrowserRouter 更改为 Router 将如何解决问题,以及问题是什么?
    • 它应该可以工作。如图所示,您是否传递了browerHistory? &lt;Router history={browserHistory}&gt;
    • 你写的和我的代码source一模一样。 BrowserRouter 等价于 Router history={history}。是的,我确实这样做了
    • 不完全是。原因是 BrowserRouter 有自己的历史。创建另一个历史记录并从中推送不会更改路由器历史记录。
    • 抱歉,我没有发现另一个问题。我已经编辑了我的答案。请尝试一下。 @塞巴斯蒂安尼尔森
    猜你喜欢
    • 2020-02-08
    • 2019-08-03
    • 1970-01-01
    • 2021-10-21
    • 2021-10-03
    • 2019-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多