skip to Main Content

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.

2

Answers


  1. 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);
    }, [])

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search