While making a post request my request is going in a loop. Not sure why it's happening. Its happening at the handleSubmit of the form. I referred few question from stackoverflow but it did not helped me. Still looking for a solution. Dammm its Ruined my SUNDAY.
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { FORGOT_PASSWORD } from "../../redux/types";
import { useDispatch, useSelector } from "react-redux";
import AuthLayout from "../../layouts/Auth";
export default function ForgotPassword() {
const dispatch = useDispatch();
const [email, setEmail] = useState("");
const handleSubmit = async (e) => {
console.log(email,'---get email')
e.preventDefault();
const payload = { email };
//loginUser(payload)
console.log(payload,'=====')
dispatch({ type: FORGOT_PASSWORD, payload });
};
return (
<AuthLayout>
<div className="container mx-auto px-4 h-full">
<div className="flex content-center items-center justify-center h-full">
<div className="w-full lg:w-4/12 px-4">
<div className="relative flex flex-col min-w-0 break-words w-full mb-6 shadow-lg rounded-lg bg-blueGray-200 border-0">
<div className="rounded-t mb-0 px-6 py-6">
<div className="text-blueGray-400 text-center mb-3 font-bold">
<center>Reset your password </center>
</div>
<hr className="mt-6 border-b-1 border-blueGray-300" />
</div>
<div className="flex-auto px-4 lg:px-10 py-10 pt-0">
<form onSubmit={handleSubmit}>
<div className="relative w-full mb-3">
<label
className="block uppercase text-blueGray-600 text-xs font-bold mb-2"
htmlFor="grid-password"
>
Email
</label>
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
type="email"
required
className="border-0 px-3 py-3 placeholder-blueGray-300 text-blueGray-600 bg-white rounded text-sm shadow focus:outline-none focus:ring w-full ease-linear transition-all duration-150"
placeholder="Email"
/>
</div>
<div className="text-center mt-6">
<button
className="bg-blueGray-800 text-white active:bg-blueGray-600 text-sm font-bold uppercase px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 w-full ease-linear transition-all duration-150"
type="submit"
>
{/* {loading ? "Sending email..." : "Reset Password"} */} Reset Password
</button>
</div>
</form>
</div>
</div>
<div className="flex flex-wrap mt-6 relative">
<div className="w-1/2">
<Link to="/auth/forgot-password" className="text-blueGray-200">
Login?
</Link>
</div>
<div className="w-1/2 text-right">
<Link to="/auth/register" className="text-blueGray-200">
Create new account
</Link>
</div>
</div>
</div>
</div>
</div>
</AuthLayout>
);
}
This is my Redux looks like
import { LOGIN, REGISTER, LOGOUT, FORGOT_PASSWORD } from "../types";
const initialState = {};
const auth = (state = initialState, { type, payload }) => {
switch (type) {
case LOGIN:
return { ...state, ...payload };
case REGISTER:
return { ...state, ...payload };
case LOGOUT:
return { ...state, ...payload };
case FORGOT_PASSWORD:
return { ...state, ...payload };
default:
return state;
}
};
export default auth;
And this is how my SAGA looks like
export function* forgotPassword({ payload }) {
yield put({ type: FORGOT_PASSWORD, payload: { loading: true } });
try {
const { status } = yield authService.forgotPassword(payload);
if (status === 204) {
const key = 'updatable';
// notification.success({ message: "Logged in successfully" });
message.loading({ content: 'Loading...', key });
message.success({ content: 'Reset password link sent to your email!', key, duration: 4 });
//window.location.replace("/dashboard");
} else yield put({ type: FORGOT_PASSWORD, payload: { loading: false } });
} catch (error) {
yield put({ type: FORGOT_PASSWORD, payload: { loading: false } });
}
}
The issue I when I submit that form it just goes in loop. INFINITE LOOP
EDIT-
After debugging I see it keep looping at SAGA and SERVICE CALL [JUST IN CASE THE API I AM CALLING HAS RESPONSE SUCCESS CODE 204]
// THIS IS SERVICE CALL
const userInstance = axios.create({
baseURL: 'http://localhost:3005/v1/',
headers: { "Content-Type": "application/json" },
timeout: 10000,
responseType: "json",
validateStatus: (status) => status < 400,
});
// BELOW IS THE API call I am making
async function forgotPassword(payload) {
return userInstance
.post("/auth/forgot-password", payload)
.then((response) => {
if (response) {
return response;
}
return false;
})
.catch((err) => console.log(err));
}
And this is my SAGA FUCNTION
export function* forgotPassword({ payload }) {
console.log('======AT SAGA', payload);
yield put({ type: FORGOT_PASSWORD, payload: payload });
try {
// here below line the SERVICE function for API call is called
const { status } = yield forgotPassword(payload);
if (status === 204) {
const key = 'updatable';
// notification.success({ message: "Logged in successfully" });
message.loading({ content: 'Loading...', key });
message.success({ content: 'Reset password link sent to your email!', key, duration: 4 });
//window.location.replace("/dashboard");
} else yield put({ type: FORGOT_PASSWORD, payload: { loading: false } });
} catch (error) {
yield put({ type: FORGOT_PASSWORD, payload: { loading: false } });
}
}
//EXPORT ALL TO ROOT
export default function* rootSaga() {
yield all([
takeEvery(LOGIN, login),
takeEvery(REGISTER, register),
takeEvery(LOGOUT, logoutUser),
]);
yield all([takeEvery(FORGOT_PASSWORD, forgotPassword)]);
}
SO AFTER DEBUGGING IT JUST KEEP LOOPING INFINITE - FROM SAGA FUNCTION TO THE SERVICE CALL FUNCTION WHERE ITs been called at SAGA.
I'm pretty sure it's because you use the action type "FORGOT_PASSWORD"
for triggering both state update in reducer and the saga function.
You said you've tried my solution. But I doubt you're still missing some points. So I'mma post the solution again in full details.
My reasoning:
put
in saga function is effectively dispatch
in redux's term. dispatch({ type: "FORGOT_PASSWORD" })
from handleSubmit
to trigger initial run of saga, the action first arrives at the redux storetakeEvery("FORGOT_PASSWORD", forgotPassword)
, it's now routed to forgotPassword
saga function forgotPassword
run some side-effects, and eventually you wanna tell the redux reducer to update the state. So you put({ type: "FORGOT_PASSWORD" })
wishing it would reach the reducer.forgotPassword
, now you're in a infinite loop. Notice throughout the above explanation I always use string literals to present action types? "FORGOT_PASSWORD"
with double quotes.
You said in the comment
those are just CONSTANTS so I think does not matter
Obviously you missed the crucial point. Off course I don't mean to change the constants variable name, I mean change the action types' string literal .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.