history.push 更改 url,但未呈现组件
history.push changes url, but component is not rendered
为什么 Dashboard
组件在 history.push("/dashboard")
将 url 更改为 /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
);
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>
}
请更换路由器。如果您这样写,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
不知道的自定义历史记录对象。 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} />
为什么 Dashboard
组件在 history.push("/dashboard")
将 url 更改为 /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
);
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>
}
请更换路由器。如果您这样写,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
不知道的自定义历史记录对象。 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} />