history.push 无法在获取回调中工作
history.push not working in fetch callback
我正在开发简单的 React js 应用程序,我在其中对用户进行身份验证,如果 he/she 已成功登录,我正在尝试重定向到主页,但我遇到了一些奇怪的情况。请帮助我完成以下代码。
下面是函数 fetchAPI
的代码,使用一些输入参数调用服务器
function fetchAPI(methodType, url, data, callback){
fetch(url,{
method: methodType,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => callback(data) )
.catch(error => callback(data));
}
现在我这样称呼它
fetchAPI("POST", Constants.LOGIN, data, function(callback) {
if(callback.status == 200) {
console.log(callback.message);
this.props.history.push("/home");
}else if( typeof callback.status != "undefined"){
alertModal("Alert", callback.message);
}
});
问题是它没有像响应条件中提到的那样重定向到 /home
,而是只打印成功消息。
但是当我像下面的代码一样直接使用 fetch api 时,它会将我重定向到 /home
谁能帮我看看为什么我会这样??
fetch(Constants.LOGIN, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => {
if (data.status == 200) {
this.props.history.push("/home");
} else if (typeof data.status != "undefined") {
alertModal("Alert", data.message);
}
})
.catch(error => callback(data));
好的,忘记回调,我去过那里,没有更多CALLBACK HELL。
始终使用承诺,您可以使用 async/await:
简化一切
async function fetchAPI(methodType, url, data){
try {
let result = await fetch(url, {
method: methodType,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}); // wait until request is done
let responseOK = response && response.ok;
if (responseOK) {
let data = await response.json();
// do something with data
return data;
} else {
return response;
}
} catch (error) {
// log your error, you can also return it to handle it in your calling function
}
}
在你的 React 组件中:
async someFunction(){
let result = await fetchAPI("POST", Constants.LOGIN, data); // wait for the fetch to complete
if (!result.error){
// get whatever you need from 'result'
this.props.history.push("/home");
} else {
// show error from 'result.error'
}
}
现在您的代码看起来更具可读性了!
fetch的错误在result.error或result.statusText,我很久以前就不用fetch了,改用Axios. Have a look at my answer on some differences between the 2 。
根据您的回答进行编辑
好的,根据您发布的代码:
import React from "react";
import Constants from "../Constants.jsx";
import { withRouter } from "react-router-dom";
class Login extends React.Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
errors: []
};
}
showValidationErr(elm, msg) {
this.setState(prevState => ({
errors: [...prevState.errors, { elm, msg }]
}));
}
clearValidationErr(elm) {
this.setState(prevState => {
let newArr = [];
for (let err of prevState.errors) {
if (elm != err.elm) {
newArr.push(err);
}
}
return { errors: newArr };
});
}
onEmailChange(e) {
this.setState({ email: e.target.value });
this.clearValidationErr("email");
}
onPasswordChange(e) {
this.setState({ password: e.target.value });
this.clearValidationErr("password");
}
submitLogin(e) {
e.preventDefault();
const { email, password } = this.state;
if (email == "") {
this.showValidationErr("email", "Email field cannot be empty");
}
if (password == "") {
this.showValidationErr("password", "Password field cannot be empty");
}
if (email != "" && password != "") {
var data = {
username: this.state.email,
password: this.state.password
};
// I added function keyword between the below line
async function someFunction(){
let result = await fetchAPI("POST", Constants.LOGIN, data); // wait for the fetch to complete
if (!result.error){
this.props.history.push("/home"); // Here is the error
} else {
// show error from 'result.error'
}
}
someFunction();
}
}
render() { ......................
####-----This is function definition------####
async function fetchAPI(methodType, url, data){
try {
let response = await fetch(url, {
method: methodType,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}); // wait until request is done
let responseOK = response && response.ok;
if (responseOK) {
let data = await response.json();
// do something with data
return data;
} else {
return response;
}
} catch (error) {
return error;
// log your error, you can also return it to handle it in your calling function
}
}
这是想法,您应该使 async
调用 API 的函数。在您的示例中,您的函数 submitLogin
必须是异步的,因为它将在内部调用异步函数。只要您调用异步函数,调用者就必须是异步的,或者相应地处理承诺。应该是这样的:
async submitLogin(e) {
e.preventDefault();
const { email, password } = this.state;
if (email == "") {
this.showValidationErr("email", "Email field cannot be empty");
}
if (password == "") {
this.showValidationErr("password", "Password field cannot be empty");
}
if (email != "" && password != "") {
var data = {
username: this.state.email,
password: this.state.password
};
let result = await fetchAPI("POST", Constants.LOGIN, data); // wait for the fetch to complete
if (!result.error) {
this.props.history.push("/home"); // Here is the error
} else {
// show error from 'result.error'
}
}
如果函数在构造函数中正确绑定,this
就不会有任何问题。您似乎没有在构造函数中绑定 submitLogin
函数,这会给您带来 this
上下文的问题。这是它应该如何绑定:
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
errors: []
};
// bind all functions used in render
this.submitLogin = this.submitLogin.bind(this);
}
查看 this article 以了解有关 this
上下文问题的更多信息。
现在,根据您提供的代码,在我看来您正处于未知领域。如果你觉得路由难找或者async/await不清楚,建议你不要用,先掌握React基础(你遇到的语法问题就是一个例子,你应该'没有把那个函数放在那里,还有 this
的绑定问题)。
例如,阅读 this post 以了解总体思路,我还建议您在使用异步、获取或路由之前尝试其他更简单的示例。当你清楚 React 生命周期后,你可以从那里继续,使用异步函数,然后是路由器。
我还建议您按照 Official docs and also have a look at this post 中的示例更好地理解 async/await。
当然给出这些建议,是为了让你在掌握React的基础上有一个清晰的基础,以后的基础不会有任何问题! :)
我正在开发简单的 React js 应用程序,我在其中对用户进行身份验证,如果 he/she 已成功登录,我正在尝试重定向到主页,但我遇到了一些奇怪的情况。请帮助我完成以下代码。
下面是函数 fetchAPI
的代码,使用一些输入参数调用服务器
function fetchAPI(methodType, url, data, callback){
fetch(url,{
method: methodType,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => callback(data) )
.catch(error => callback(data));
}
现在我这样称呼它
fetchAPI("POST", Constants.LOGIN, data, function(callback) {
if(callback.status == 200) {
console.log(callback.message);
this.props.history.push("/home");
}else if( typeof callback.status != "undefined"){
alertModal("Alert", callback.message);
}
});
问题是它没有像响应条件中提到的那样重定向到 /home
,而是只打印成功消息。
但是当我像下面的代码一样直接使用 fetch api 时,它会将我重定向到 /home
谁能帮我看看为什么我会这样??
fetch(Constants.LOGIN, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => {
if (data.status == 200) {
this.props.history.push("/home");
} else if (typeof data.status != "undefined") {
alertModal("Alert", data.message);
}
})
.catch(error => callback(data));
好的,忘记回调,我去过那里,没有更多CALLBACK HELL。
始终使用承诺,您可以使用 async/await:
简化一切async function fetchAPI(methodType, url, data){
try {
let result = await fetch(url, {
method: methodType,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}); // wait until request is done
let responseOK = response && response.ok;
if (responseOK) {
let data = await response.json();
// do something with data
return data;
} else {
return response;
}
} catch (error) {
// log your error, you can also return it to handle it in your calling function
}
}
在你的 React 组件中:
async someFunction(){
let result = await fetchAPI("POST", Constants.LOGIN, data); // wait for the fetch to complete
if (!result.error){
// get whatever you need from 'result'
this.props.history.push("/home");
} else {
// show error from 'result.error'
}
}
现在您的代码看起来更具可读性了!
fetch的错误在result.error或result.statusText,我很久以前就不用fetch了,改用Axios. Have a look at my answer on some differences between the 2
根据您的回答进行编辑
好的,根据您发布的代码:
import React from "react";
import Constants from "../Constants.jsx";
import { withRouter } from "react-router-dom";
class Login extends React.Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
errors: []
};
}
showValidationErr(elm, msg) {
this.setState(prevState => ({
errors: [...prevState.errors, { elm, msg }]
}));
}
clearValidationErr(elm) {
this.setState(prevState => {
let newArr = [];
for (let err of prevState.errors) {
if (elm != err.elm) {
newArr.push(err);
}
}
return { errors: newArr };
});
}
onEmailChange(e) {
this.setState({ email: e.target.value });
this.clearValidationErr("email");
}
onPasswordChange(e) {
this.setState({ password: e.target.value });
this.clearValidationErr("password");
}
submitLogin(e) {
e.preventDefault();
const { email, password } = this.state;
if (email == "") {
this.showValidationErr("email", "Email field cannot be empty");
}
if (password == "") {
this.showValidationErr("password", "Password field cannot be empty");
}
if (email != "" && password != "") {
var data = {
username: this.state.email,
password: this.state.password
};
// I added function keyword between the below line
async function someFunction(){
let result = await fetchAPI("POST", Constants.LOGIN, data); // wait for the fetch to complete
if (!result.error){
this.props.history.push("/home"); // Here is the error
} else {
// show error from 'result.error'
}
}
someFunction();
}
}
render() { ......................
####-----This is function definition------####
async function fetchAPI(methodType, url, data){
try {
let response = await fetch(url, {
method: methodType,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}); // wait until request is done
let responseOK = response && response.ok;
if (responseOK) {
let data = await response.json();
// do something with data
return data;
} else {
return response;
}
} catch (error) {
return error;
// log your error, you can also return it to handle it in your calling function
}
}
这是想法,您应该使 async
调用 API 的函数。在您的示例中,您的函数 submitLogin
必须是异步的,因为它将在内部调用异步函数。只要您调用异步函数,调用者就必须是异步的,或者相应地处理承诺。应该是这样的:
async submitLogin(e) {
e.preventDefault();
const { email, password } = this.state;
if (email == "") {
this.showValidationErr("email", "Email field cannot be empty");
}
if (password == "") {
this.showValidationErr("password", "Password field cannot be empty");
}
if (email != "" && password != "") {
var data = {
username: this.state.email,
password: this.state.password
};
let result = await fetchAPI("POST", Constants.LOGIN, data); // wait for the fetch to complete
if (!result.error) {
this.props.history.push("/home"); // Here is the error
} else {
// show error from 'result.error'
}
}
如果函数在构造函数中正确绑定,this
就不会有任何问题。您似乎没有在构造函数中绑定 submitLogin
函数,这会给您带来 this
上下文的问题。这是它应该如何绑定:
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
errors: []
};
// bind all functions used in render
this.submitLogin = this.submitLogin.bind(this);
}
查看 this article 以了解有关 this
上下文问题的更多信息。
现在,根据您提供的代码,在我看来您正处于未知领域。如果你觉得路由难找或者async/await不清楚,建议你不要用,先掌握React基础(你遇到的语法问题就是一个例子,你应该'没有把那个函数放在那里,还有 this
的绑定问题)。
例如,阅读 this post 以了解总体思路,我还建议您在使用异步、获取或路由之前尝试其他更简单的示例。当你清楚 React 生命周期后,你可以从那里继续,使用异步函数,然后是路由器。
我还建议您按照 Official docs and also have a look at this post 中的示例更好地理解 async/await。
当然给出这些建议,是为了让你在掌握React的基础上有一个清晰的基础,以后的基础不会有任何问题! :)