React调度进入无限循环



在发出post请求时,我的请求会循环进行。不知道为什么会这样。它发生在表单的句柄Submit上。我提到了stackoverflow的一些问题,但这对我没有帮助。仍在寻找解决方案。该死,它毁了我的星期天。

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>
);
}

这是我的Redux,看起来像

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;

这就是我的SAGA看起来像的样子

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 } });
}
}

当我提交表格时,问题就循环了。无限循环

编辑-

调试后,我看到它在SAGA和SERVICE CALL处保持循环[万一API I AM CALING 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));
}

这是我的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)]);
}

所以在调试之后,它只是无限循环——从SAGA函数到在SAGA调用它的服务调用函数。

我很确定这是因为您使用操作类型"FORGOT_PASSWORD"来触发reducer中的状态更新和saga函数。

你说你已经试过我的解决方案了。但我怀疑你还是遗漏了一些要点。因此,我将再次发布解决方案的全部细节。

我的理由:

saga函数中的
  1. put实际上是redux术语中的dispatch
  2. dispatch({ type: "FORGOT_PASSWORD" })handleSubmit触发传奇的初始运行,动作首先到达redux存储
  3. saga中间件之所以采取行动,是因为takeEvery("FORGOT_PASSWORD", forgotPassword),它现在被路由到forgotPasswordsaga函数
  4. forgotPassword运行了一些副作用,最终您希望告诉redux reducer更新状态。所以你put({ type: "FORGOT_PASSWORD" })希望它能到达减速器
  5. 令人惊讶的是,这个动作在步骤3中再次被saga中间件接收,并被路由回forgotPassword,现在您处于无限循环中

注意到在上面的解释中,我总是使用字符串文字来表示操作类型?带双引号的"FORGOT_PASSWORD"

你在评论中说

这些只是常数,所以我认为无关紧要

显然你错过了关键点。当然,我不是要更改常量变量名,而是要更改操作类型的字符串文字。

最新更新