如何在 React 中重定向到另一个视图
Posted
技术标签:
【中文标题】如何在 React 中重定向到另一个视图【英文标题】:How to redirect to another view in React 【发布时间】:2020-10-16 18:25:40 【问题描述】:我正在开发一个需要登录的应用程序,单击登录按钮后,我需要重定向到另一个布局中的另一个视图,我尝试使用 this.props.history.push("/Inicio ") 在登录成功时重定向。在这种情况下,这是路径。
path: "/Inicio",
name: "Inicio",
component: Inicio,
layout: "/admin"
,
这是完整的代码
import React, Component from "react";
import
Grid,
Col
from "react-bootstrap";
import Card from "components/Card/Card.jsx";
import FormInputs from "components/FormInputs/FormInputs.jsx";
import Button from "components/CustomButton/CustomButton.jsx";
class Login extends Component
constructor(props)
super(props)
this.state =
users: [],
user: '',
pass: '',
msg: '',
apiResponse:''
this.logChange = this.logChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this)
handleSubmit(event)
event.preventDefault()
var data =
user: this.state.user,
pass: this.state.pass,
msg: this.state.msg,
apiResponse: this.state.apiResponse
console.log(data)
fetch("http://localhost:9000/log/Login",
method: 'POST',
headers: 'Content-Type': 'application/json',
body: JSON.stringify(data)
).then(function(response)
if (response.status >= 400)
throw new Error("Bad response from server");
return response.json();
).then((data) =>
if(data == "success")
console.log(data)
this.setState(users: data);
this.props.history.push("/Inicio");
window.location.reload();
else
if(data == 'El usuario o la contraseña no coinciden')
this.setState( apiResponse: data )
).catch(function(err)
console.log(err)
);
logChange(e)
this.setState([e.target.name]: e.target.value);
render()
return (
<div className="content">
<p class="col-md-4"></p>
<Grid >
<Col md=5>
<Card
title="Login"
content=
<form method='POST' onSubmit= this.handleSubmit>
<p class="col-md-2"></p>
<FormInputs
ncols=["col-md-7"]
properties=[
label: "Usuario",
type: "text",
bsClass: "form-control",
placeholder: "Usuario",
maxlength: 20 ,
name: "user",
onChange: this.logChange
]
/>
<p class="col-md-2"></p>
<FormInputs
ncols=["col-md-7"]
properties=[
label: "Contraseña",
type: "password",
bsClass: "form-control",
placeholder: "Contraseña",
maxlength: 20,
name: "pass",
onChange: this.logChange
]
/>
<p >this.state.apiResponse</p>
<br/>
<br/>
<Button bsStyle="info" pullRight fill type="submit">
Login
</Button>
<Button bsStyle="info" pullLeft fill type="submit">
Olvide mi Contraseña
</Button>
</form>
/>
</Col>
</Grid>
</div>
);
export default Login;
但在 handleSubmit() 中一切正常,除了 this.props.history.push("/Inicio") 因为它什么也没做。
index.js 代码
import React from "react";
import ReactDOM from "react-dom";
import BrowserRouter, Route, Switch, Redirect from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import "./assets/css/animate.min.css";
import "./assets/sass/light-bootstrap-dashboard-react.scss?v=1.3.0";
import "./assets/css/demo.css";
import "./assets/css/pe-icon-7-stroke.css";
import AdminLayout from "layouts/Admin.jsx";
import LoginLayout from "layouts/LoginLayout.jsx";
import EfoodLayout from "layouts/EFoodLayout.jsx";
ReactDOM.render(
<BrowserRouter>
<Switch>
<Route path="/admin" render=props => <AdminLayout ...props /> />
<Route path="/login" render=props => <LoginLayout ...props /> />
<Route path="/Efood" render=props => <EfoodLayout ...props /> />
<Redirect from="/" to="/login/Login" />
</Switch>
</BrowserRouter>,
document.getElementById("root")
);
登录布局
import React, Component from "react";
import Route, Switch from "react-router-dom";
import LoginNavbar from "components/Navbars/LoginNavbar";
import Footer from "components/Footer/Footer";
import routes from "routes.js";
class Login extends Component
getRoutes = routes =>
return routes.map((prop, key) =>
if (prop.layout === "/login")
return (
<Route
path=prop.layout + prop.path
render=props => (
<prop.component
...props
handleClick=this.handleNotificationClick
/>
)
key=key
/>
);
else
return null;
);
;
getBrandText = path =>
return "Bienvenido a E Food";
;
render()
return (
<div className="wrapper">
<LoginNavbar
brandText=this.getBrandText(this.props.location.pathname)
/>
<Switch>this.getRoutes(routes)</Switch>
<Footer />
</div>
);
export default Login;
希望你能帮助我,并感谢所有回答的人。 PD:如果您需要我的代码中的更多内容,请告诉我。
【问题讨论】:
有问题的组件是由Route
在Router
内渲染以接收路由道具,还是用withRouter
HOC 装饰?您能否更新整个组件代码,以及您的路由是什么样的?
与此同时,您似乎没有将班级的this
正确绑定到handleSubmit
。您将this
分配给变量self
并且当您尝试仍然使用this
时,它正上方self
用于更新状态。将this
保存到变量self
并不是您真正需要在反应中使用的模式。如果您可以使用整个组件和路由器代码更新您的问题,我们将更好地了解正在发生的事情。
感谢您的回答,正如我在下面所说的,我是新来使用 react,我已经从我在 Internet 上找到的模板中检索了我的所有前端,我已经编辑它看起来像我想要,所以我真的不知道它到底是如何工作的,我知道组件是什么,但我真的不知道这是否是我的想法,路由器也是如此,如果你不介意我可以通过 GitHub 或其他方式向您发送整个代码,前提是您当然接受我不想打扰您。
如果您可以在您的问题中发布相关代码,那就太好了,但是指向您的存储库的链接总比没有好。通常不建议使用代码链接,因为内容可能会更改、移动或删除,这样问题就会失去上下文。
非常感谢,我已经用问题的整个代码和 index.js 编辑了帖子,我希望这会有所帮助,如果没有,我会在这里发布我的 repo 链接,当然,当您访问该链接时,我会删除它以避免出现问题。
【参考方案1】:
好的,因为很明显您要在其中进行导航的组件是一个深度嵌套的组件,所以有几个选项。
道具钻孔(不推荐)
prop drilling
道具钻探的缺点是,如果一开始没有传递正确的道具,或者如果任何组件在此过程中忘记传递道具,那么某些子组件将无法接收他们需要什么,并且可能很难追踪丢失的内容或原因。由于现在对 this 组件的任何更改都需要关注它周围的所有其他组件,因此维护起来更加困难。道具钻孔实际上是一种反应反模式。
登录布局
您的LoginLayout
组件似乎使用了一个路由配置对象并动态呈现路由。它需要传递从其父级接收到的路由道具。此处和您要使用 history.push
的 Login
之间的任何组件都需要继续向下传递所有道具。
class Login extends Component
getRoutes = routes =>
return routes.map((prop, key) =>
if (prop.layout === "/login")
return (
<Route
path=prop.layout + prop.path
render=props => (
<prop.component
...props
...this.props // <-- Pass on all props passed to this component
handleClick=this.handleNotificationClick
/>
)
key=key
/>
);
else
return null;
);
;
...
render()
return (
...
);
使用withRouter
高阶组件(推荐)
withRouter
您可以访问
history
对象的属性和最近的<Route>
的match
通过 withRouter 高阶组件。withRouter
将更新的match
、location
和history
道具传递给被包装的 组件无论何时呈现。
import React, Component from "react";
import withRouter from 'react-router-dom'; // <-- import HOC
import Grid, Col from "react-bootstrap";
import Card from "components/Card/Card.jsx";
import FormInputs from "components/FormInputs/FormInputs.jsx";
import Button from "components/CustomButton/CustomButton.jsx";
class Login extends Component
constructor(props)
...
handleSubmit(event)
event.preventDefault();
var data =
user: this.state.user,
pass: this.state.pass,
msg: this.state.msg,
apiResponse: this.state.apiResponse
;
console.log(data);
fetch("http://localhost:9000/log/Login",
method: "POST",
headers: "Content-Type": "application/json" ,
body: JSON.stringify(data)
)
.then(function(response)
if (response.status >= 400)
throw new Error("Bad response from server");
return response.json();
)
.then(data =>
if (data == "success")
console.log(data);
this.setState( users: data );
this.props.history.push("/Inicio"); // <-- history prop should now exist
window.location.reload();
else
if (data == "El usuario o la contraseña no coinciden")
this.setState( apiResponse: data );
)
.catch(function(err)
console.log(err);
);
logChange(e)
this.setState( [e.target.name]: e.target.value );
render()
return (
<div className="content">
...
</div>
);
export default withRouter(Login); // <-- decorate Login with HOC
【讨论】:
非常感谢您的宝贵时间和帮助!今晚我将尝试使用 withRouther。 :) @FranHerrera 欢迎您。如果此答案充分解决了您的问题,请标记并接受答案,如果您发现它有帮助或信息丰富,那么也请点赞。干杯。【参考方案2】:您是否使用react-router-dom
来处理您的路由?如果是这样,您可以使用the hooks to navigate。
import useHistory from "react-router-dom";
...
const history = useHistory()
...
history.push('/Inicio')
请注意,这仅适用于 React 版本 >= 16.8
您的代码无法运行的原因是绑定。
使用this.props.history.push("/Inicio")
时,this
指的是您所在的函数,而不是组件历史记录。
如果你想保持你的代码那样,你可以简单地将你的函数变成一个箭头函数:
.then((data) =>
if(data == "success")
console.log(data)
self.setState(users: data);
**this.props.history.push("/Inicio")** // now this will be correct
**window.location.reload();** // no need, react handles the reload
else
if(data == 'El usuario o la contraseña no coinciden')
self.setState( apiResponse: data )
不过,我强烈建议使用 react 的最新功能(检查钩子,它真的很有用)。
【讨论】:
React hooks.... 功能组件。 OP 显然在使用基于类的组件。 @DrewReese 这就是为什么我也用他自己的代码回答,但仍然建议他换成功能组件 这就像把你的 X 品牌汽车送到修理工那里修理,修理工说:“好吧,我开的是 Y 品牌,它可以工作,所以你也应该开 Y 品牌的车。”它没有解释为什么 OP 的代码没有按预期工作并且没有开始解决它。不过,您可能会对函数绑定有所了解。 感谢您的回答,您能告诉我在哪里可以看到 react 版本吗?老实说,我是新来使用 react 的,我从模板中检索了所有前端,所以我真的不知道知道我的反应版本。 我已经尝试过使用 '''import useHistory from "react-router-dom"; ... const history = useHistory() ... history.push('/Inicio')''' 但它告诉我这个错误 Attempted import error: 'useHistory' is not export from 'react-路由器域'。以上是关于如何在 React 中重定向到另一个视图的主要内容,如果未能解决你的问题,请参考以下文章