Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop. (Next-js) Toggle Component

huangapple go评论80阅读模式
英文:

Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop. (Next-js) Toggle Component

问题

以下是你要翻译的内容:

"I want to set a component to only be visible if the user wants to edit the content of an entry.
The problem is the error stated in the title.

I used setState to set a boolean @ toggle, setToggle and then conditionally render the component UpdateReservation (at the bottom of the tsx) based off of that. Every rendered item should have it´s own button for editing.

Other solutions on here did not help. maybe i am overlooking something. Thanks in advance for the help.

This is the first part of the file:"

以下是渲染的部分:

return (
    <>
      <div className="flex flex-col items-center justify-around p-24 text-[#2E3A59]">
        <h1 className='mt-8 text-[50px] font-bold'>Bookings</h1>
        <div>
          <Link href="/booking" className="m-2 flex items-center h-fit w-fit border-2 border-[#FFA500] py-1 px-4 gap-[12px] text-[20px] font-bold hover:scale-110 hover:bg-[#7EC699] hover:text-[#2E3A59] duration-300">
            MAKE RESERVATION
          </Link>
          <div>
            <div className='m-2'>
              <p className='text-lg font-bold m-2'>Reservations for <strong>{format(parseISO(selectedDay), 'do MMM yyyy', { locale: de })}</strong></p>

              <div className='flex flex-row'>
                <button
                  onClick={decreaseDay}
                >
                  -1 Day
                </button>
                <button
                  onClick={setToday}
                >
                  TODAY
                </button>
                <button
                  onClick={increaseDay}
                >
                  +1 Day
                </button>
              </div>
            </div>
            <p className='text-lg font-bold m-2'>Total reservations: {index}</p>
            <div className='m-6 p-6 mb-12 w-[90vw] h-fit flex flex-row flex-wrap items-start flex-center'>

              {sortedTables?.map((reservation) => (
                <div key={reservation.id} className="m-1 p-1 border h-fit w-fit border-black">
                  <p className="font-bold">NAME: {reservation.name} {reservation.surname}</p>
                  <div className='w-full bg-black h-[2px]' />
                  <p><strong>email: </strong>{reservation.email}</p>
                  <p><strong>phone: </strong>{reservation.phone}</p>
                  <p><strong>Time: </strong>{format(parseISO(reservation.date), 'do MMM yyyy', { locale: de })},{format(parseISO(reservation.date), 'kk:mm', { locale: de })}</p>
                  <p><strong>Seats: </strong>{reservation.seats}</p>
                  <p className='max-w-[280px]'><strong>Message: </strong>{reservation.message}</p>
                  <div className='w-full bg-black h-[2px]' />
                  <div className='flex flex-row justify-around'>
                    <button
                      onClick={() => handleDelete(reservation.id)}
                      className='text-xs text-red-500 border-red-500 border-2 p-1 m-1 rounded-md hover:scale-110 duration-300 hover:text-white hover:bg-red-500'
                    >
                      Delete
                    </button>

                    <button
                      onClick={() => toggleEdit(reservation.id)}
                      className='text-xs text-green-500 border-green-500 border-2 p-1 m-1 rounded-md hover:scale-110 duration-300 hover:text-white hover:bg-green-500'
                    >
                      Edit
                    </button>


                  </div>
                </div>
              ))}

            </div>
            <div>

              {toggle && (
                <UpdateReservation days={days} closedDays={closedDays} id={currentId} toggleEdit={toggleEdit} />
              )}

            </div>

          </div>
        </div>
      </div>
    </>
  )
};

希望这能帮助你解决问题。

英文:

I want to set a component to only be visible if the user wants to edit the content of an entry.
The problem is the error stated in the title.

I used setState to set a boolean @ toggle, setToggle and then conditionally render the component UpdateReservation (at the bottom of the tsx) based off of that. Every rendered item should have it´s own button for editing.

Other solutions on here did not help. maybe i am overlooking something. Thanks in advance for the help.

This is the first part of the file:

function tables({ days, closedDays }: HomeProps) {

  /**
   * SET STATES HERE
   * @param toggle handles visibilty of UpdateReservation
   * @param selectedDay is the currently selected day
   */
  const [toggle, setToggle] = useState<boolean>(initToggle);
  const [selectedDay, setSelectedDay] = useState<string>(initDate);

  // ID OF ITEM
  let currentId: string = "";

  /**
   * TOGGLE VISIBILITY OF UpdateReservation
   * @param id is the id of the toggled reservation
   */
  function toggleEdit(id: string) {
    setToggle(!toggle);
    currentId = id;
  };

  //tRPC
  const { mutateAsync: addItem } = trpc.admin.bookReservation.useMutation();
  const { data: reservations, refetch } = trpc.admin.getReservations.useQuery();
  const { mutateAsync: updateReservation } = trpc.admin.updateReservation.useMutation();
  const { mutateAsync: deleteReservation } = trpc.admin.deleteReservation.useMutation();

  /**
   * FUNCTIONS TO SELECT DAY
   * INCREASE OR DECREASE BY 1 DAY
   */
  function setToday() {
    setSelectedDay(initDate);
  }

  function increaseDay() {
    const date: Date = addDays(parseISO(selectedDay), 1);
    setSelectedDay(formatISO(date));
  };

  function decreaseDay() {
    const date: Date = subDays(parseISO(selectedDay), 1);
    setSelectedDay(formatISO(date));
  };

  /**
   * USE EFFECTS
   */
  useEffect(() => {
    setSelectedDay
    console.log("useEffect, selectedDay");
  }, [selectedDay]);

  useEffect(() => {
    setToggle
    console.log("useEffect, setToggle");
    console.log("currentId", currentId);
  }, [toggle])

  /**
   * HANDLE DELETION OF RESERVATION
   * @param id id of reservation
   */
  const handleDelete = async (id: string) => {
    await deleteReservation({ id });
    refetch();
  };

  /**
   * Filters reservations before rendering to only show reservations for the selected date
   */
  const filterTablesByDate = reservations?.filter((reservation) => {

    const formatDate: string | undefined = reservation.date.split('T')[0]
    const formatSelectedDay: string | undefined = selectedDay.split('T')[0]

    if (formatDate === formatSelectedDay) {
      return reservation;
    };

  });

  /**
   * filteredTablesbyDate will get sorted from earliest to latest booking for the corresponding day
   */
  const sortedTables = filterTablesByDate?.sort((a: any, b: any) => {
    const aDate: Date = new Date(a.date);
    const bDate: Date = new Date(b.date);

    const aTime: number = aDate.getTime();
    const bTime: number = bDate.getTime();

    return aTime - bTime;
  });

And this one the rendered tsx:

return (
    <>
      <div className="flex flex-col items-center justify-around p-24 text-[#2E3A59]">
        <h1 className='mt-8 text-[50px] font-bold'>Bookings</h1>
        <div>
          <Link href="/booking" className="m-2 flex items-center h-fit w-fit border-2 border-[#FFA500] py-1 px-4 gap-[12px] text-[20px] font-bold hover:scale-110 hover:bg-[#7EC699] hover:text-[#2E3A59] duration-300">
            MAKE RESERVATION
          </Link>
          <div>
            <div className='m-2'>
              <p className='text-lg font-bold m-2'>Reservations for <strong>{format(parseISO(selectedDay), 'do MMM yyyy', { locale: de })}</strong></p>

              <div className='flex flex-row'>
                <button
                  onClick={decreaseDay}
                >
                  -1 Day
                </button>
                <button
                  onClick={setToday}
                >
                  TODAY
                </button>
                <button
                  onClick={increaseDay}
                >
                  +1 Day
                </button>
              </div>
            </div>
            <p className='text-lg font-bold m-2'>Total reservations: {index}</p>
            <div className='m-6 p-6 mb-12 w-[90vw] h-fit flex flex-row flex-wrap items-start flex-center'>

              {sortedTables?.map((reservation) => (
                <div key={reservation.id} className="m-1 p-1 border h-fit w-fit border-black">
                  <p className="font-bold">NAME: {reservation.name} {reservation.surname}</p>
                  <div className='w-full bg-black h-[2px]' />
                  <p><strong>email: </strong>{reservation.email}</p>
                  <p><strong>phone: </strong>{reservation.phone}</p>
                  <p><strong>Time: </strong>{format(parseISO(reservation.date), 'do MMM yyyy', { locale: de })},{format(parseISO(reservation.date), 'kk:mm', { locale: de })}</p>
                  <p><strong>Seats: </strong>{reservation.seats}</p>
                  <p className='max-w-[280px]'><strong>Message: </strong>{reservation.message}</p>
                  <div className='w-full bg-black h-[2px]' />
                  <div className='flex flex-row justify-around'>
                    <button
                      onClick={() => handleDelete(reservation.id)}
                      className='text-xs text-red-500 border-red-500 border-2 p-1 m-1 rounded-md hover:scale-110 duration-300 hover:text-white hover:bg-red-500'
                    >
                      Delete
                    </button>

                    <button
                      onClick={() => toggleEdit(reservation.id)}
                      className='text-xs text-green-500 border-green-500 border-2 p-1 m-1 rounded-md hover:scale-110 duration-300 hover:text-white hover:bg-green-500'
                    >
                      Edit
                    </button>


                  </div>
                </div>
              ))}

            </div>
            <div>

              {toggle && (
                <UpdateReservation days={days} closedDays={closedDays} id={currentId} toggleEdit={toggleEdit} />
              )}

            </div>

          </div>
        </div>
      </div>
    </>
  )
};

export async function getServerSideProps() {
  const days = await prisma.day.findMany();
  const closedDays = (await prisma.closedDay.findMany()).map((d) => formatISO(d.date));
  return { props: { days, closedDays } };
};

export default tables;

I tried a couple of solutions I found on here but none really made a difference. I always got the same error as mentioned in the title.

答案1

得分: 1

只是想指出,这个useEffect会在循环中运行,因为它在依赖数组中有toggle,而在useEffect中,您又设置了状态setToggle,这会再次设置toggle并重新渲染组件。

改成这样试试:

useEffect(() => {
  console.log("useEffect, setToggle");
  console.log("currentId", currentId);
}, [])
英文:

Just want to point out that this useEffect will run in the loop because it has toggle in the dependency array and in the useEffect you are setting the state setToggle again which sets the toggle again and rerenders the component.

> useEffect(() => {
setToggle
console.log("useEffect, setToggle");
console.log("currentId", currentId);
}, [toggle])

Instead try this

> useEffect(() => {
setToggle
console.log("useEffect, setToggle");
console.log("currentId", currentId);
}, [])

答案2

得分: 0

不要在依赖项中放置 setState,因为这会导致重新渲染次数过多。以下是当你这样做时发生的情况分解。
首先,组件挂载并且 useEffect 运行其函数。
其次,在 useEffect 回调函数中,setState 触发并引发重新渲染。
第三,因为你将状态放在 useEffect 的依赖项中,并且在第二步中更改了它,React 将重新渲染此组件。
最后,组件再次挂载,所有这些步骤再次运行... 这就是循环的逻辑。

英文:

dont put setState in useEffect while state is in the dependencies. because this leadas to too many re-renders. here is the breakdown of whats happening when you do that.
first component mounts and useEffect runs its function.
second, in useEffect callback function setState fires and makes a re-render
third, because you put state in the dependency of useEffect and you change it in second, react will re-render this component.
finally, component again mounts and all these steps runs again ... here is the logic of the loop.

huangapple
  • 本文由 发表于 2023年7月14日 02:35:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76682346.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定