Home > OS >  React too many renders in useState if else statement
React too many renders in useState if else statement

Time:11-07

I want to render the page according to parameter in URL.

export default function Navbar() {
  const [leftHeader, setLeftHeader] = useState("aa");
  if (window.location.href.indexOf("/admin/aa") !== -1) {
    console.log("aa");
    setLeftHeader("aa");
  } else if (window.location.href.indexOf("/admin/bb") !== -1) {
    console.log("bb");
    setLeftHeader("bb");
  } else if (window.location.href.indexOf("/admin/cc") !== -1) {
    console.log("cc");
    setLeftHeader("cc");
  } else if (window.location.href.indexOf("/admin/dd") !== -1) {
    console.log("dd");
    setLeftHeader("dd");
  } else if (window.location.href.indexOf("/admin/ee") !== -1) {
    console.log("ee");
    setLeftHeader("ee");
  } else {
    console.log("ff"); //when i clicked any element on sidebar, I always get the Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
    setLeftHeader("ff");
  }

  return (
    <>
      {/* Navbar */}
      <nav className="absolute top-0 left-0 w-full z-10 bg-transparent md:flex-row md:flex-nowrap md:justify-start flex items-center p-4">
        <div className="w-full mx-autp items-center flex justify-between md:flex-nowrap flex-wrap md:px-12 px-4">
          {/* Brand */}
          <a
            className="text-white text-xl uppercase hidden lg:inline-block font-semibold"
            href="#pablo"
            onClick={(e) => e.preventDefault()}
          >
            {leftHeader} {/* This code show the parameters in URL */}
          </a>

          <ul className="flex-col md:flex-row list-none items-center hidden md:flex">
            <UserDropdown />
          </ul>
        </div>
      </nav>
      {/* End Navbar */}
    </>
  );
}

But this code always gives the Error: Too many re-renders. React limits the number of renders to prevent an infinite loop. How can i fix that?

CodePudding user response:

The problem is that when you call setLeftHeader it triggers a component re-render, causing the chain of if statements to run again, triggering another re-render infinitely. The solution is to use the useEffect hook to only run the conditional code when the component is mounted:

export default function Navbar() {
  const [leftHeader, setLeftHeader] = useState("aa");

  useEffect(() => {
    if (window.location.href.indexOf("/admin/aa") !== -1) {
      console.log("aa");
      setLeftHeader("aa");
    } else if (window.location.href.indexOf("/admin/bb") !== -1) {
      console.log("bb");
      setLeftHeader("bb");
    } else if (window.location.href.indexOf("/admin/cc") !== -1) {
      console.log("cc");
      setLeftHeader("cc");
    } else if (window.location.href.indexOf("/admin/dd") !== -1) {
      console.log("dd");
      setLeftHeader("dd");
    } else if (window.location.href.indexOf("/admin/ee") !== -1) {
      console.log("ee");
      setLeftHeader("ee");
    } else {
      console.log("ff");
      setLeftHeader("ff");
    }
  }, [])

  return (
    <>
      {/* Navbar */}
      <nav className="absolute top-0 left-0 w-full z-10 bg-transparent md:flex-row md:flex-nowrap md:justify-start flex items-center p-4">
        <div className="w-full mx-autp items-center flex justify-between md:flex-nowrap flex-wrap md:px-12 px-4">
          {/* Brand */}
          <a
            className="text-white text-xl uppercase hidden lg:inline-block font-semibold"
            href="#pablo"
            onClick={(e) => e.preventDefault()}
          >
            {leftHeader} {/* This code show the parameters in URL */}
          </a>

          <ul className="flex-col md:flex-row list-none items-center hidden md:flex">
            <UserDropdown />
          </ul>
        </div>
      </nav>
      {/* End Navbar */}
    </>
  );
}

CodePudding user response:

you can fix that by using react router and useEffect where you subscribe to route change and set your state only if the route changed not on every component re-render

  • Related