'My Toggle/Click event re-renders entire component each time on click?

I have a toggle to show/hide a specific DIV and change the button text based on the current React Hook State. When I view the console log, every single time I click it re-renders the complete page again in Next.js. Not 100% sure if this is normal, But I don't think this should happen if you only toggle one element.

useEffect you can pass property to say whether a specific state is changed or not.

Is there a smarter way of toggling an element and changing its text on click? Without having to re-render the complete code but only the part that you are working with.

import { useEffect, useState } from "react";

import { NextPage } from "next";
import Head from "next/head";
import Link from "next/link";

import HeroModule from "@modules/HeroModule";
import VideoModule from "@modules/VideoModule";
import ImageModule from "@modules/ImageModule";
import SliderModule from "@modules/SliderModule";
import QuoteModule from "@modules/QuoteModule";
import PreFooterModule from "@modules/PreFooterModule";

import Footer from "@components/Footer";
import Comments from "@components/Comments";

const Article: NextPage = () => {
  const btnClass = "bg-transparent";
  const text = "Reactie plaatsen";
  const [buttonActive, setButtonActive] = useState(btnClass);
  const [buttonText, setButtonText] = useState(text);
  const [openForm, setOpenForm] = useState(false);

  const onToggleForm = () => {
    setOpenForm(!openForm);

    if (!openForm) {
      setButtonText("Sluiten");
      setButtonActive("bg-navyBlue text-white");
    } else {
      setButtonActive("bg-transparent text-navyBlue");
      setButtonText(text);
    }
  };

  return (
    <>
      <Head>
        <title>Artikel Detail</title>
        <meta name="author" content="" />
        <meta name="description" content="Developed by Friends For Brands" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <HeroModule
        title="De headline van deze tekstuele content"
        text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
      />

      <div className="max-w-screen-xl px-6 pt-16 pb-12 mx-auto border-b-2 border-gray-300 lg:px-8 text-navyBlue ">
        <div className="grid w-full grid-cols-12 gap-6">
          <aside className=" lg:col-span-3 col-span-full">
            <div className="grid grid-cols-12 lg:sticky lg:top-5 lg:block">
              <div className="col-span-2 mb-4 avatar">
                <div className="w-16 h-16 sm:h-20 sm:w-20 md:w-24 md:h-24 rounded-full ring ring-[#65c3c8] ring-offset-base-100 ring-offset-2">
                  <img src="https://i.pravatar.cc/300" alt="" />
                </div>
              </div>

              <div className="col-span-8 leading-2">
                <p className="font-bold">John Doe</p>
                <p>Marketing Manager</p>

                <p className="mt-2 md:mt-6">00/00/0000</p>
                <p>Leestijd 10 minuten</p>

                <div className="mt-6 card-actions">
                  <Link href="/tag/fashion" passHref>
                    <span className="text-[11px] font-semibold uppercase cursor-pointer badge badge-outline hover:bg-navyBlue hover:text-white">
                      Fashion
                    </span>
                  </Link>
                  <Link href="/tag/products" passHref>
                    <span className="text-[11px] font-semibold uppercase cursor-pointer badge badge-outline hover:bg-navyBlue hover:text-white">
                      Products
                    </span>
                  </Link>
                </div>
              </div>
            </div>
          </aside>
          <main className="leading-relaxed col-span-full lg:col-span-9 md:text-normal">
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
              eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
              enim ad minim veniam, quis nostrud exercitation ullamco laboris
              nisi ut aliquip ex ea commodo consequat.
            </p>

            <h2 className="mt-3 text-3xl md:text-4xl">Heading 2</h2>
            <h3 className="mt-3 text-2xl md:text-3xl">Heading 3</h3>
            <h4 className="mt-3 text-xl md:text-2xl">Heading 4</h4>

            <ul className="pl-6 my-4 list-disc">
              <li>Lorem ipsum dolor sit amet</li>
              <li>
                Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
                labore
              </li>
              <li>Et dolore magna aliqua. Ut enim ad minim veniam</li>
              <li>
                Quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
                commodo consequat.
              </li>
            </ul>
            <h2 className="mt-6 text-3xl md:text-4xl">H2: Tussentitel</h2>
            <ul className="pl-6 my-4 list-decimal">
              <li>Lorem ipsum dolor sit amet</li>
              <li>
                Consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
                labore
              </li>
              <li>Et dolore magna aliqua. Ut enim ad minim veniam</li>
              <li>
                Quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
                commodo consequat.
              </li>
            </ul>
            <h5 className="font-bold">Tussentitel paragraaf</h5>
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
              eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
              enim ad minim veniam, quis nostrud exercitation ullamco laboris
              nisi ut aliquip ex ea commodo consequat.
            </p>
            <h3 className="mt-6 text-2xl md:text-3xl">H3: Video Module</h3>
            <VideoModule id="mkggXE5e2yk" platform="youtube" />
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
              eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
              enim ad minim veniam, quis nostrud exercitation ullamco laboris
              nisi ut aliquip ex ea commodo consequat.
            </p>
            <h3 className="mt-6 text-2xl md:text-3xl">H3: Image Module</h3>
            <ImageModule
              url="https://images.pexels.com/photos/1193743/pexels-photo-1193743.jpeg"
              caption="Photo of multicolored abstract painting"
              alt="A Pexels image"
            />
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
              eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
              enim ad minim veniam, quis nostrud exercitation ullamco laboris
              nisi ut aliquip ex ea commodo consequat.
            </p>
            <h3 className="mt-6 text-2xl md:text-3xl">H3: Slider Module</h3>
            <SliderModule />
            <p>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
              eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
              enim ad minim veniam, quis nostrud exercitation ullamco laboris
              nisi ut aliquip ex ea commodo consequat.
            </p>
            <h3 className="mt-6 text-2xl md:h2text-3xl">H3: Quote Module</h3>
            <QuoteModule />
          </main>
        </div>
      </div>

      <div className="w-full max-w-4xl px-4 py-20 mx-auto">
        <div className="flex gap-4">
          <h2 className="text-4xl">Comment Module</h2>
          <button
            onClick={onToggleForm}
            className={`items-center justify-center px-4 py-2 text-xs font-medium uppercase transition duration-150 ease-in-out ${buttonActive} border rounded-full shadow-sm cursor-pointer  border-navyBlue place-self-start sm:mt-0 hover:border-transparent hover:bg-navyBlue hover:text-white`}
          >
            {buttonText}
          </button>
        </div>

        {openForm && <p>OPEN</p>}
      </div>

      {/* <Comments isOpen={openForm} toggleForm={onToggleForm} /> */}

      <PreFooterModule />
      <Footer />
    </>
  );
};

export default Article;


Solution 1:[1]

You can wrap onToggleForm in useCallback to memoize it. Then that function won't be recreated with every render. Also, be aware that using react strict mode will purposely double render to help you catch any side effects (a good thing and only happens in debug). So you can temporarily remove the <React.StrictMode> tags and see if your console.logs() stop doubling up.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dave