简体   繁体   English

反应调度进入无限循环

[英]React dispatch going in the infinite loop

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.我从stackoverflow提到了几个问题,但它没有帮助我。 Still looking for a solution.仍在寻找解决方案。 Dammm its Ruined my SUNDAY. Dammm 它毁了我的星期天。

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

And this is how my SAGA looks like这就是我的 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 } });
  }
}

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]调试后,我看到它一直在 SAGA 和 SERVICE CALL 处循环 [仅以防万一我正在调用的 API 有响应成功代码 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这就是我的 SAGA 功能

  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.所以在调试后它只是保持无限循环 - 从 SAGA FUNCTION 到服务呼叫 FUNCTION,它在 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.我很确定这是因为您使用操作类型"FORGOT_PASSWORD"来触发减速器中的 state 更新和传奇 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:我的推理:

  1. put in saga function is effectively dispatch in redux's term. put saga function 在 redux 的术语中是有效的dispatch
  2. You dispatch({ type: "FORGOT_PASSWORD" }) from handleSubmit to trigger initial run of saga, the action first arrives at the redux store你从handleSubmit dispatch({ type: "FORGOT_PASSWORD" })触发saga的初始运行,action首先到达redux store
  3. The saga middleware pickup the action because takeEvery("FORGOT_PASSWORD", forgotPassword) , it's now routed to forgotPassword saga function saga 中间件因为takeEvery("FORGOT_PASSWORD", forgotPassword)了这个动作,现在它被路由到了forgotPassword saga function
  4. forgotPassword run some side-effects, and eventually you wanna tell the redux reducer to update the state. forgotPassword运行了一些副作用,最终你想告诉 redux 减速器更新 state。 So you put({ type: "FORGOT_PASSWORD" }) wishing it would reach the reducer.所以你put({ type: "FORGOT_PASSWORD" })希望它能到达减速器。
  5. Surprisingly, this action is once again pickup by the saga middleware in step 3, routed back to forgotPassword , now you're in a infinite loop.令人惊讶的是,这个动作再次被步骤 3 中的 saga 中间件拾取,路由回forgotPassword ,现在您处于无限循环中。

Notice throughout the above explanation I always use string literals to present action types?请注意在上面的解释中我总是使用字符串文字来表示动作类型? "FORGOT_PASSWORD" with double quotes. "FORGOT_PASSWORD"带双引号。

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 .当然,我并不是要更改常量变量名称,而是要更改操作类型的string literal

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM