Search code examples
reactjsmern

Too many re-renders. React limits the number of renders to prevent an infinite loop. and


I am working on a mern application in my code I have created many components and use react state hook and react context api hook for managing data flow through application but when in a component where many states already exist i create a new state it shows me error my new state code is attached

 const [a, seta] = useState("garg");
  seta("naman");

My applications stops after showing many warnings which are warning 1:-

    at renderWithHooks (react-dom.development.js:14997)
    at mountIndeterminateComponent (react-dom.development.js:17811)
    at beginWork (react-dom.development.js:19049)
    at HTMLUnknownElement.callCallback (react-dom.development.js:3945)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994)
    at invokeGuardedCallback (react-dom.development.js:4056)
    at beginWork$1 (react-dom.development.js:23964)
    at performUnitOfWork (react-dom.development.js:22776)
    at workLoopSync (react-dom.development.js:22707)
    at renderRootSync (react-dom.development.js:22670)
    at performSyncWorkOnRoot (react-dom.development.js:22293)
    at react-dom.development.js:11327
    at unstable_runWithPriority (scheduler.development.js:468)
    at runWithPriority$1 (react-dom.development.js:11276)
    at flushSyncCallbackQueueImpl (react-dom.development.js:11322)
    at flushSyncCallbackQueue (react-dom.development.js:11309)
    at flushPassiveEffectsImpl (react-dom.development.js:23620)
    at unstable_runWithPriority (scheduler.development.js:468)
    at runWithPriority$1 (react-dom.development.js:11276)
    at flushPassiveEffects (react-dom.development.js:23447)
    at react-dom.development.js:23324
    at workLoop (scheduler.development.js:417)
    at flushWork (scheduler.development.js:390)
    at MessagePort.performWorkUntilDeadline (scheduler.development.js:157)

warning 2:-

    at App (http://localhost:3000/static/js/main.chunk.js:82:81)

My code of component where i wrote above code for state update

import React, { useState, useContext, useEffect } from "react";
import Modal from "react-modal";
import { UserContext } from "./UserContext";
import { AllUserContext } from "./UserContext";
import AlertContext from "./AlertContext";
import Calendar from "react-calendar";
import "../index.css";
import PayModal from "./PayModal";
import { DateContext } from "./UserContext";
import SplitModal from "./SplitModal";
import { ListContext } from "./UserContext";
function Addexpense({ setModal, modal }) {
  const [description, setDescription] = useState("");
  const [payer, setPayer] = useState("you");
  const [cost, setCost] = useState();
  const [paymodal, setpaymodal] = useState(false);
  const [dtmodal, setdtmodal] = useState(false);
  const [splitmodal, setsplitmodal] = useState(false);
  // const { listobj, setlistobj } = useContext(ListContext);
  const { user, userfriend, usrbalance, setBalance, expense, setExpense } =
    useContext(UserContext);
  let b = usrbalance;
  const [value, onChange] = useState(new Date());
  const [a, seta] = useState("json");
  seta("naman");
  var today = value;
  var dd = String(today.getDate()).padStart(2, "0");
  var mm = today.toLocaleString("default", { month: "long" });
  var yyyy = today.getFullYear();
  today = mm + " " + dd + ", " + yyyy;
  const [tags, setTag] = useState([]);
  const [list, setList] = useState([user.name]);
  const [listobj, setlistobj] = useState({ exp: {} });
  let _list = { ...listobj };
  _list.exp[user.name] = 0;
  // setlistobj(_list);
  console.log(listobj, "list", _list.exp);

  useEffect(() => {
    setdtmodal(false);
  }, [value]);
  const addtag = (e) => {
    let filter;
    userfriend.map((f) => {
      if (f === e.target.value) {
        filter = f;
      }
    });
    console.log(filter);
    if (filter) {
      setTag([...tags, e.target.value]);
      setList([...list, e.target.value]);
      e.target.value = "";
    }
  };
  const removetag = (i) => {
    let a;
    setTag(
      tags.filter((n, index) => {
        a = n;
        return index != i;
      })
    );
    setList(
      list.filter((_, index) => {
        return index != i;
      })
    );
    console.log(a);
  };
  const m = { color: "red" };
  console.log(tags);
  const saveexpense = async () => {
    if (payer === "you") {
      console.log(tags.length);
      b = b + (cost / (tags.length + 1)) * tags.length;
    } else {
      b = b - cost / (tags.length + 1);
    }

    console.log(b);
    const response = await fetch("http://localhost:5000/api/auth/addexpense", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "auth-token": localStorage.getItem("token"),
      },
      body: JSON.stringify({
        balance: b,
        expenses: tags,
      }),
    });
    const json = await response.json();
    setBalance(json.user3.balance);
    console.log(json.user3);
  };
  return (
    <div>
      <Modal isOpen={modal} className=" expmodalbox ">
        <div
          style={{
            backgroundColor: "#1cc29f",
            border: "1px solid #eeeeee",
            padding: "5px",
            display: "flex",
            borderRadius: "10px 10px 0px 0px",
            color: "white",
          }}
        >
          <h5 style={{ marginLeft: "150px" }}>Add an Expense</h5>
          <button
            style={{ position: "absolute", right: "10px" }}
            onClick={() => {
              setModal(false);
            }}
          >
            <i class="fas fa-times" />
          </button>
        </div>
        <div className="  exp-input p-2">
          <label style={{ width: "190px" }} htmlFor="">
            With You and:
          </label>
          <div style={{ position: "relative" }}>
            <ul className=" grid grid-cols-3  gap-2 ">
              {tags.map((t, i) => {
                console.log(t);
                return (
                  <li className="flex align-items-center" key={i}>
                    <img
                      src="https://s3.amazonaws.com/splitwise/uploads/user/default_avatars/avatar-grey47-50px.png"
                      alt=""
                    />
                    <span className="mx-1">{t}</span>
                    <button
                      style={{ color: "#c0c0c0" }}
                      onClick={() => {
                        removetag(i);
                      }}
                    >
                      <i class="fas fa-times" />
                    </button>
                  </li>
                );
              })}
              <input
                type="text"
                placeholder={tags.length ? null : "Enter name"}
                onKeyUp={(e) => {
                  {
                    return e.key === "Enter" ? addtag(e) : null;
                  }
                }}
                style={{ flex: "1" }}
              />
            </ul>
          </div>
        </div>
        {tags.length ? (
          <div>
            <div className="bg-white">
              <div className="px-5 pt-4 pb-2 flex exp-main-1">
                <img
                  src="https://s3.amazonaws.com/splitwise/uploads/category/icon/square_v2/uncategorized/[email protected]"
                  alt=""
                />
                <div className="ml-3">
                  <div className="desc">
                    {" "}
                    <input
                      type="text"
                      name=""
                      id=""
                      placeholder="Enter a description"
                      onChange={(e) => setDescription(e.target.value)}
                    />
                  </div>
                  <div className="cost mt-2">
                    {" "}
                    <span style={{ fontSize: "40px" }}>₹</span>
                    <input
                      type="number"
                      name=""
                      id=""
                      placeholder="0.00"
                      onChange={(e) => setCost(e.target.value)}
                    />
                  </div>
                </div>
              </div>
              <div className="exp-main-2 ml-28 mt-2 ">
                <div>
                  {" "}
                  Paid by{" "}
                  <button
                    onClick={() => {
                      setpaymodal(true);
                    }}
                  >
                    {payer}
                  </button>{" "}
                  and split{" "}
                  <button
                    onClick={() => {
                      setsplitmodal(true);
                    }}
                  >
                    unequally{usrbalance}
                  </button>
                  .
                </div>
                <span className="ml-20">(₹0.00/person)</span>
              </div>
              <div className="exp-main-3">
                <button onClick={() => setdtmodal(true)}>{today}</button>
              </div>
            </div>
          </div>
        ) : null}
        <div className="exp-bottom ">
          <div className="exp-bottom-btn">
            {" "}
            <button className="cancel"> Cancel</button>
            <button
              className="ml-3 save"
              onClick={() => {
                saveexpense();
              }}
            >
              Save{" "}
            </button>
          </div>
        </div>
        {paymodal ? (
          <PayModal setpaymodal={setpaymodal} setPayer={setPayer} />
        ) : null}
        {splitmodal ? (
          <SplitModal
            setsplitmodal={setsplitmodal}
            tags={tags}
            list={list}
            cost={cost}
          />
        ) : null}
        {dtmodal ? (
          <div className="dtmodal">
            <div
              style={{
                backgroundColor: "#1cc29f",
                border: "1px solid #eeeeee",
                padding: "5px",
                display: "flex",
                borderRadius: "10px 10px 0px 0px",
                color: "white",
              }}
            >
              <h5 style={{ marginLeft: "100px" }}>Choose Date</h5>
              <button
                style={{ position: "absolute", right: "10px" }}
                onClick={() => {
                  setdtmodal(false);
                  {
                    console.log("vh");
                  }
                }}
              >
                <i class="fas fa-times" />
              </button>
            </div>
            <div className="bg-white px-2 pt-2">
              <Calendar onChange={onChange} value={value} className="my" />
            </div>
          </div>
        ) : null}
      </Modal>
    </div>
  );
}

export default Addexpense;

my app.js

import { useState, useEffect } from "react";
import "./index.css";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Navbar from "./Components/Navbar";
import Home from "./Components/Home";
import Footer from "./Components/Footer";
import Login from "./Components/Login";
import Signup from "./Components/Signup";
import { MyAlert } from "./Components/AlertContext";
import { AuthContext } from "./Components/AuthContext";
import Dashboard from "./Components/Dashboard";
import { UserContext } from "./Components/UserContext";
import { AllUserContext } from "./Components/UserContext";
import { UserFriendContext } from "./Components/UserContext";
import { BalanceContext } from "./Components/UserContext";
import { ExpenseContext } from "./Components/UserContext";
import { DateContext } from "./Components/UserContext";
import Loggedout from "./Components/Loggedout";
import { ListContext } from "./Components/UserContext";
function App() {
  const [auth, setAuth] = useState(false);
  const [user, setUser] = useState({});
  const [allusers, setAll] = useState([]);
  const [userfriend, setuserfriend] = useState([]);
  const [date, setDate] = useState("naman");
  const [usrbalance, setBalance] = useState();
  const [expense, setExpense] = useState([]);
  const [listobj, setlistobj] = useState({ exp: {} });
  const myname = [];
  // const [t,sett]=useState(1);
  // useEffect(() => {
  //   const timer=setTimeout(() => {
  //     sett(t+1)
  //   }, 1000);
  //   // Clear timeout if the component is unmounted
  //   return () => clearTimeout(timer);
  // });
  const getuser = async (e) => {
    const response = await fetch("http://localhost:5000/api/auth/fetchuser", {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
        "auth-token": localStorage.getItem("token"),
      },
    });
    const json = await response.json();

    console.log(json);
    setUser(json);
    setuserfriend(json.friends);
    setBalance(json.balance);
    setExpense(json.expenses);
    console.log(userfriend);
  };
  useEffect(() => {
    getuser();

    console.log("naman gar");
  }, [auth]);
  console.log(user.friends, "kutta");
  const getallusers = async (e) => {
    const response = await fetch(
      "http://localhost:5000/api/auth/fetchalluser",
      {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
        },
      }
    );
    const json = await response.json();
    console.log(json);
    json.map((u) => {
      myname.push(u.name);
      console.log(myname);
      setAll(myname);
    });
  };
  useEffect(() => {
    if (localStorage.getItem("token")) {
      setAuth(true);

      getallusers();

      console.log("auth is true");
    } else {
      console.log("Auth is false");
    }
  }, [auth]);
  return (
    <>
      <Router>
        <MyAlert>
          <ListContext.Provider value={{ listobj, setlistobj }}>
            <DateContext.Provider value={{ date, setDate }}>
              <AllUserContext.Provider value={{ allusers, setAll }}>
                <UserContext.Provider
                  value={{
                    user,
                    setUser,
                    setuserfriend,
                    userfriend,
                    usrbalance,
                    setBalance,
                    expense,
                    setExpense,
                  }}
                >
                  <AuthContext.Provider value={{ auth, setAuth }}>
                    <Navbar />
                    <Switch>
                      <Route path="/" component={Home} exact></Route>
                      <Route path="/Login" component={Login} exact></Route>
                      <Route path="/Signup" component={Signup} exact></Route>

                      <Route
                        path="/Dashboard"
                        component={auth ? Dashboard : Loggedout}
                        exact
                      ></Route>
                    </Switch>
                  </AuthContext.Provider>
                </UserContext.Provider>
              </AllUserContext.Provider>
            </DateContext.Provider>
          </ListContext.Provider>
        </MyAlert>
      </Router>
    </>
  );
}

export default App;

Solution

  • This code will cause an infinite rerender loop:

    const [a, seta] = useState("garg");
    seta("naman");
    

    The reason is that each seta (or any setState in general) react rerender and execute what is inside the component and when he find another seta it will rerender again and execute the code again and so on.

    To prevent this from happening either you have to give the default value on useState('default value'), or if you want to give a value when component mount you can use useEffect like this:

    useEffect(() => {
        seta("naman")
    }, [])