I hope you are fine, I have a problem canceling my axios request with the useEffect hook in ReactJS.
Explanation
First of all, you should know that my code uses a file called Requests.js, there my custom requests are stored, such as: signup, start session and consult user information.
In these functions I receive the url, the data to send and some headers.
When I use these functions in my main code I pass a cancellation token created by axios, this token is created when the form is submitted, and if the user leaves the page in that timeframe, I cancel the axios request.
Where you may have the problem is how I pass the cancellation token to axios, since I pass it in function in function, until I get to the function of axios.
Request.js
import { LOGIN_URL, SIGNUP_URL, GET_INFO_USER_LOGGED } from "../Config/api";
import { alertDanger } from "./notifications";
class Requests {
_showNetworkErrorAlert(status) {
if (status >= 400 && status < 500) {
alertDanger("A client network error occurred.");
} else if (status >= 500 && status < 600) {
alertDanger("Platform server error.");
} else {
alertDanger("A connection error occurred.");
}
}
async _post(url, args, headers) {
console.log({ ...headers });
try {
const res = await axios.post(
url,
{
...args,
},
{
...headers, // here I receive the headers (including the cancellation token)
}
);
return res;
} catch (error) {
this._showNetworkErrorAlert(error?.response?.status);
}
}
async _get(url, args, headers) {
console.log(headers);
try {
const res = await axios.get(url, {
...args,
headers,
});
return res;
} catch (error) {
this._showNetworkErrorAlert(error.response.status);
}
}
async login({ email, password, headers }) {
// here I pass the parameters with the headers (and the cancellation token)
const loginUser = await this._post(LOGIN_URL, { email, password }, headers);
return loginUser;
}
async signup({ username, email, password, headers }) {
const signupUser = await this._post(
SIGNUP_URL,
{
username,
email,
password,
},
headers // Here same as the previous ones
);
return signupUser;
}
async getInfoUserLogged(token) {
const userInfoLogged = await this._get(
GET_INFO_USER_LOGGED,
{},
{
authorization: `Bearer ${token}`,
}
);
return userInfoLogged?.data?.data?.user;
}
}
export default new Requests();
My file generating the problem.
import { Redirect } from "react-router-dom";
import axios from "axios";
// import { useSelector } from 'react-redux';
// components
import LoginComponent from "./LoginComponent";
import { alertDanger, alertSuccess } from "../../../Helpers/notifications";
// Redux elements
import { connect } from "react-redux";
import { SetCurrentUserInfo } from "../../../Redux/Actions/UserActions";
// api links
import Resquests from "../../../Helpers/Resquests";
const LoginContainer = (props) => {
const [credentials, setCredentials] = useState({
email: "",
password: "",
});
const [isLogged, setLogged] = useState(false);
const [isLoading, setLoading] = useState(false);
let cancelResquest = null;
/*
This cancellation of the petition DOES NOT WORK
*/
useEffect(() => {
return () =>
cancelResquest && cancelResquest.cancel("Finalizando peticion");
}, []);
const onChangeCredentials = ({ target }) => {
setCredentials({
...credentials,
[target.name]: target.value,
});
};
const onSubmitForm = async (ev) => {
ev.preventDefault();
setLoading(true);
/*
Here I generate my token when the form is submitted
*/
cancelResquest = axios.CancelToken.source();
const res = await Resquests.login(
{
email: credentials.email,
password: credentials.password,
}, // The third parameter is the "headers"
{
cancelToken: cancelResquest.token, // the token
}
);
setLoading(false);
if (res?.data?.ok === false) {
alertDanger("Error in your credentials");
} else if (res?.data?.ok === true) {
alertSuccess("Successful login.");
const userInfoLogged = await Resquests.getInfoUserLogged(
res.data.data.token
);
props.SetCurrentUserInfo(userInfoLogged);
console.log("en la linea 49", props.UserInformation);
setLogged(true);
}
};
console.log("en la linea 53", props.UserInformation);
return isLogged ? (
<Redirect to="/" />
) : (
<LoginComponent
{...{ onChangeCredentials, ...credentials, onSubmitForm, isLoading }}
/>
);
};
const mapStateToProps = (state) => ({
UserInformation: state.UserInformation,
});
const mapDispatchToProps = {
SetCurrentUserInfo,
};
export default connect(mapStateToProps, mapDispatchToProps)(LoginContainer);
Thank you very much in advance for reading this.