history.push 更改了 url,但未呈现组件

时间:2021-05-19 22:10:29

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

为什么 Dashboard 将 url 更改为 history.push("/dashboard") 后未呈现 /dashboard 组件?

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


index.js

import ReactDOM from "react-dom";

import Router from "./Router";

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

登录表单.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>
}

2 个答案:

答案 0 :(得分: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;

并且仍然使用 LoginForm HOC 装饰 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);

建议

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

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

答案 1 :(得分:0)

请更换路由器。如果这样写,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>
        )
    }
}