【问题标题】:Maximum update depth exceeded in React reduxReact redux 中超过了最大更新深度
【发布时间】:2022-01-17 23:51:44
【问题描述】:

iam new bie for react, react-redux 我的问题是当我尝试点击登录 api 并尝试使用状态布尔值并重定向到仪表板时,它显示 错误:超出最大更新深度。当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,可能会发生这种情况。 React 限制了嵌套更新的数量以防止无限循环。,我实际上使用的是基于函数组件的 react,比如钩子,请参见下面的代码

这是我的登录组件:-

import React, { useEffect, useState, useRef } from "react";
import { Link } from "react-router-dom";
import { useSelector, useDispatch } from "react-redux";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { userRegistration, userLoginProcess } from "../actions/user";
import * as constants from "../actions/types";
import SimpleReactValidator from "simple-react-validator";
import { isLoggedIn } from "./../utils/helper";
import { Redirect } from "react-router";

const Login = (props) => {
  const [formData, setFormData] = useState({
    email: "",
    password: "",
  });

  const { email, password } = formData;
  const simpleValidator = useRef(
    new SimpleReactValidator({
      className: "text-danger",
    })
  );
  const [, forceUpdate] = useState();

  const handleChange = (e) => {
    setFormData({ ...formData, [e.target.name]: e.target.value });
  };

  const dispatch = useDispatch();
  const { showToast } = useSelector((state) => state.userRegister);
  const { isLoading, isAuthenticated } = useSelector(
    (state) => state.userLogin
  );
  useEffect(() => {
    if (showToast) {
      toast.success("Registration Success !", {
        position: toast.POSITION.TOP_CENTER,
      });
      dispatch({
        type: constants.REGISTER_CLEAR,
      });
    }
  }, []);

  const handleLogin = (e) => {
    e.preventDefault();
    const loginformValid = simpleValidator.current.allValid();
    if (!loginformValid) {
      simpleValidator.current.showMessages();
      forceUpdate(1);
    } else {
      dispatch(userLoginProcess(formData));
    }
  };
  if (isLoggedIn() == true || isAuthenticated == true) {
    return <Redirect to="/user-dashboard" />;
  }
  return (
    <div className="min-h-screen bg-gray-100 flex flex-col justify-center sm:py-12">
      <ToastContainer />
      <div className="p-10 xs:p-0 mx-auto md:w-full md:max-w-md">
        <h1 className="font-bold text-center text-2xl mb-5">DBC Login</h1>
        <div className="bg-white shadow w-full rounded-lg divide-y divide-gray-200">
          <form onSubmit={(e) => handleLogin(e)}>
            <div className="px-5 py-7">
              <label className="font-semibold text-sm text-gray-600 pb-1 block">
                E-mail
              </label>
              <input
                type="text"
                name="email"
                value={email}
                onChange={(e) => handleChange(e)}
                className="border rounded-lg px-3 py-2 mt-1 mb-5 text-sm w-full"
              />
              {simpleValidator.current.message(
                "Email ",
                formData.email,
                "required"
              )}
              <label className="font-semibold text-sm text-gray-600 pb-1 block">
                Password
              </label>
              <input
                type="password"
                name="password"
                value={password}
                onChange={(e) => handleChange(e)}
                className="border rounded-lg px-3 py-2 mt-1 mb-5 text-sm w-full"
              />
              {simpleValidator.current.message(
                "Password ",
                formData.password,
                "required"
              )}
              <button
                type="submit"
                className="transition duration-200 bg-blue-500 hover:bg-blue-600 focus:bg-blue-700 focus:shadow-sm focus:ring-4 focus:ring-blue-500 focus:ring-opacity-50 text-white w-full py-2.5 rounded-lg text-sm shadow-sm hover:shadow-md font-semibold text-center inline-block"
              >
                <span className="inline-block mr-2">Login</span>
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke="currentColor"
                  className="w-4 h-4 inline-block"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    strokeWidth="2"
                    d="M17 8l4 4m0 0l-4 4m4-4H3"
                  />
                </svg>
              </button>
            </div>
          </form>
          <div className="py-5">
            <div className="grid grid-cols-2 gap-1">
              <div className="text-center sm:text-left whitespace-nowrap">
                <button className="transition duration-200 mx-5 px-5 py-4 cursor-pointer font-normal text-sm rounded-lg text-gray-500 hover:bg-gray-100 focus:outline-none focus:bg-gray-200 focus:ring-2 focus:ring-gray-400 focus:ring-opacity-50 ring-inset">
                  <svg
                    xmlns="http://www.w3.org/2000/svg"
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke="currentColor"
                    className="w-4 h-4 inline-block align-text-top"
                  >
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      strokeWidth="2"
                      d="M8 11V7a4 4 0 118 0m-4 8v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2z"
                    />
                  </svg>
                  <span className="inline-block ml-1">Forgot Password</span>
                </button>
              </div>
              <div className="text-center sm:text-right  whitespace-nowrap">
                <button className="transition duration-200 mx-5 px-5 py-4 cursor-pointer font-normal text-sm rounded-lg text-gray-500 hover:bg-gray-100 focus:outline-none focus:bg-gray-200 focus:ring-2 focus:ring-gray-400 focus:ring-opacity-50 ring-inset">
                  <svg
                    xmlns="http://www.w3.org/2000/svg"
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke="currentColor"
                    className="w-4 h-4 inline-block align-text-bottom   "
                  >
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      strokeWidth="2"
                      d="M18.364 5.636l-3.536 3.536m0 5.656l3.536 3.536M9.172 9.172L5.636 5.636m3.536 9.192l-3.536 3.536M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-5 0a4 4 0 11-8 0 4 4 0 018 0z"
                    />
                  </svg>
                  <Link to="register" className="inline-block ml-1">
                    Sign Up
                  </Link>
                </button>
              </div>
            </div>
          </div>
        </div>
        <div className="py-5">
          <div className="grid grid-cols-2 gap-1">
            <div className="text-center sm:text-left whitespace-nowrap">
              <button className="transition duration-200 mx-5 px-5 py-4 cursor-pointer font-normal text-sm rounded-lg text-gray-500 hover:bg-gray-200 focus:outline-none focus:bg-gray-300 focus:ring-2 focus:ring-gray-400 focus:ring-opacity-50 ring-inset">
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke="currentColor"
                  className="w-4 h-4 inline-block align-text-top"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    strokeWidth="2"
                    d="M10 19l-7-7m0 0l7-7m-7 7h18"
                  />
                </svg>
                <Link to="/" className="inline-block ml-1">
                  Back to Home
                </Link>
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};
export default Login;

这是我的操作(user.js):-

import axios from "axios";
import * as constants from "../actions/types";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { Redirect } from "react-router";

var headers = {
  Accept: "application/json",
  "Content-Type": "application/json",
};
export const userRegistration = (rgData) => async (dispatch) => {
  dispatch({
    type: constants.REGISTER_REQUEST,
  });
  try {
    await axios.post("api/signup", rgData, { headers: headers }).then((res) => {
      console.log(res);
      dispatch({
        type: constants.REGISTER_SUCCESS,
      });
    });
  } catch (error) {
    dispatch({
      type: constants.REGISTER_ERROR,
    });
    //console.log(error.response);
    //var tempErr = []
    if (error.response?.data?.errors) {
      Object.keys(error.response.data.errors).forEach(function (vals) {
        //tempErr.push(error.response.data.errors[vals][0]);
        toast.error(error.response.data.errors[vals][0], {
          position: toast.POSITION.TOP_CENTER,
        });
      });
    }
  }
};

export const userLoginProcess = (lgData) => async (dispatch) => {
  dispatch({
    type: constants.LOGIN_REQUEST,
  });
  try {
    await axios
      .post("api/signin", lgData, { headers: headers })
      .then((lres) => {
        dispatch({
          type: constants.LOGIN_SUCCESS,
          returnLoginData: lres.data.token,
          returnUserData: JSON.stringify(lres.data.user),
        });
        localStorage.setItem("user_token", lres.data.token);
        localStorage.setItem(
          "userDetails",
          JSON.stringify({
            name: lres.data.user.name,
            email: lres.data.user.email,
            id: lres.data.user.id,
          })
        );
      });
  } catch (error) {
    dispatch({
      type: constants.LOGIN_ERROR,
    });
    toast.error(error.response.data.message, {
      position: toast.POSITION.TOP_CENTER,
    });
  }
};

这是我的减速器(userLogin.js):-

import {
  LOGIN_REQUEST,
  LOGIN_ERROR,
  LOGIN_SUCCESS,
  LOGOUT_REQUEST,
  LOGOUT_SUCCESS,
  LOGOUT_ERROR,
} from "../actions/types";

const initialState = {
  isLoading: false,
  isAuthenticated: false,
  token: null,
  error: "",
  success: "",
};

export default function (state = initialState, action) {
  switch (action.type) {
    case LOGIN_REQUEST:
      return {
        ...state,
        isLoading: true,
        isAuthenticated: false,
        success: "",
      };
    case LOGIN_SUCCESS:
      return {
        ...state,
        isLoading: true,
        isAuthenticated: true,
        token: action.returnRegData,
        success: "login success",
      };
    case LOGIN_ERROR:
      return {
        ...state,
        isLoading: false,
        isAuthenticated: false,
        error: "login error",
        success: "",
      };

    case LOGOUT_REQUEST:
      return {
        ...state,
        isLoading: true,
        isAuthenticated: false,
        success: "",
      };
    case LOGOUT_SUCCESS:
      return {
        ...state,
        isLoading: false,
        isAuthenticated: false,
        token: "",
        success: "",
      };
    case LOGOUT_ERROR:
      return {
        ...state,
        isLoading: false,
        isAuthenticated: false,
        error: "login error",
        success: "",
      };
    default:
      return state;
  }
}

下面是 PrivateRoute.js

import React from "react";
import { Route, Redirect } from "react-router-dom";
import { useSelector, useDispatch } from "react-redux";
import { isLoggedIn } from "../../utils/helper";
import { userLoginProcess } from "../../actions/user";

const PrivateRoutes = ({ component: Component, ...rest }) => {
  const { isAuthenticated, isLoading } = useSelector(
    (state) => state.userLogin
  );
  //console.log("Login ",state)
  // return <Route {...rest} render={(props) => <Component {...props} />}/>
  return (
    <Route
      {...rest}
      render={(props) =>
        !isLoggedIn() || isAuthenticated ? (
          <Redirect to="/login" />
        ) : (
          <Component {...props} />
        )
      }
    />
  );
};

export default PrivateRoutes;

在上面的 PrivateRoute.js 中,当我删除 login 和 Authenticated 条件时,它不会显示该错误,但是当我输入该条件时,它会显示该错误。

下面是我的 utils 文件夹下的 helper.js。

export const isLoggedIn = () => {
    return (localStorage.getItem('user_token') != null) ? true : false;
}

以下是我得到的错误:-

当我签入网络选项卡时,我可以看到其调用 localhost:3000/anonymous,URL 状态再次进入登录错误并因此导致此错误,请查看以下屏幕截图

谁能帮我解决这个问题?

【问题讨论】:

    标签: reactjs react-redux react-hooks


    【解决方案1】:

    什么是 isLoggedIn ? 我认为在这个函数中是一个错误。

    if (isLoggedIn() == true || isAuthenticated == true) {
        return <Redirect to="/user-dashboard" />;
    }
    

    并阅读useEffect 的教程。 应该是这样的。

    useEffect(() => {
        if (showToast) {
          toast.success("Registration Success !", {
            position: toast.POSITION.TOP_CENTER
          });
          dispatch({
            type: constants.REGISTER_CLEAR
          });
        }
      }, [dispatch, showToast]);
    

    【讨论】:

    • 您好,抱歉回复晚了,isLoggedIn 是一个辅助函数,假设如果用户刷新页面,状态会恢复到默认状态,所以我使用了一个辅助函数,它是在辅助文件中设置的,因此如果存在令牌,它将重定向到仪表板。以及如何解决这个问题?
    • @Jerin。您可以选择不进行此项检查。尝试 c 来执行此操作。在令牌case LOGIN_REQUEST: return { ...state, isLoading: true, isAuthenticated: !!action.returnRegData success: "", }; case LOGIN_SUCCESS: return { ...state, isLoading: true, isAuthenticated: !!action.returnRegData, token: action.returnRegData, success: "login success", }; 上设置“isAuthenticated”检查并像这样修复:if (isAuthenticated) { return &lt;Redirect to="/user-dashboard" /&gt;; }
    • 嗨@Alexander Kosykh,我试过它不起作用,还有一件事,我正在使用 PrivateRoute.js 看到上面的代码,我已经更新了 PrivateRoute.js 及其相关描述。
    • 嗨@Jerin Monish。您在渲染中调用函数 isLoggedInd() 。这是错误的。你能删除这个功能吗?你能展示一下这个函数里面有什么吗?
    • 嗨@Alexander Kosykh,它只是一个简单的功能,只是检查用户是否登录,检查上面我更新的代码。如果我在 Login.js 中删除 isLogged() 并检查 isAuthenticated 函数,它会说同样的错误,请帮助
    猜你喜欢
    • 1970-01-01
    • 2022-01-16
    • 2019-04-03
    • 2019-12-13
    • 2019-05-28
    • 2019-12-03
    • 2020-12-31
    • 2020-11-27
    • 1970-01-01
    相关资源
    最近更新 更多