reactjs React抱怨我造成了太多的重新渲染

qij5mzcb  于 2023-02-08  发布在  React
关注(0)|答案(1)|浏览(140)

renderDialogue函数应该在窗口小于654px时渲染Dialogue,否则应该更新expandMenu的状态为false,但是React说重新渲染太多,怎么解决?

const [expandMenu, setExpandMenu] = useState(false); 

const handleOpenMenu = () => {
  setExpandMenu(!expandMenu);
};

const renderDialogue = () => {
    if (window.innerWidth < 654) {
      return (
        <Dialog
          open={expandMenu}
          handler={() => handleOpenMenu()}
          size={"xl"}
          className={"bg-transparent shadow-none "}
        >
          <DialogBody>
            <div className={"relative"}>
              <img
                src={"/imgFolder2/cloud.webp"}
                className={"h-full float-center"}
              />
              <ul className="flex flex-col justify-center h-[75%] gap-5 text-2xl text-center absolute top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] w-[55%]">
                {NavItems()}
              </ul>
            </div>
          </DialogBody>
        </Dialog>
      );
    } else {
      setExpandMenu(false);
      return <> </>;
    }
  };

下面是NavItems函数,它迭代一个链接数组。

const NavItems = () => {
    return paths.map((path, idx) => (
      <li key={idx}>
        <Link
          href={getPath(idx)}
          className={`text-black block ${
            isSelectedPath(getName(idx, true))
              ? "border-b-4 border-buttonBG"
              : ""
          }`}
          onClick={() => {
            if (window.innerWidth < 654) setExpandMenu(!expandMenu);
          }}
        >
          {getName(idx)}
        </Link>
      </li>
    ));
  };
jgzswidk

jgzswidk1#

首先,当窗口大小改变时,组件不会重新呈现,这意味着根据窗口宽度显示内容的if语句只会在第一次呈现时触发,这可能很好,但不推荐。
第二,你的错误“太多的重新呈现”是因为你直接在你的组件中调用setExpandMenu。每次你更新你的expandMenu状态,这个组件都会重新呈现。然后你再次更新它,所以它会再次重新呈现。看到这里的无限循环了吗?
下面是一个你想要的工作示例,包括更新窗口大小。我已经添加了注解来解释发生了什么:

const [expandMenu, setExpandMenu] = useState(false); 
    const [windowWidth, setWindowWidth] = useState(0)

       useEffect(() => { // This will update your state depending on your window size
        function updateSize() {
        setWindowWidth(window.innerWidth)
          

        }
        window.addEventListener('resize', updateSize);
        updateSize();
        return () => window.removeEventListener('resize', updateSize);
      }, []);

      const handleOpenMenu = () => {
        setExpandMenu(!expandMenu);
      };

    const renderDialogue = () => {

        
        if (windowWidth > 654 || expandMenu) {
          return (
            <Dialog
              open={expandMenu}
              handler={() => handleOpenMenu()}
              size={"xl"}
              className={"bg-transparent shadow-none "}
            >
              <DialogBody>
                <div className={"relative"}>
                  <img
                    src={"/imgFolder2/cloud.webp"}
                    className={"h-full float-center"}
                  />
                  <ul className="flex flex-col justify-center h-[75%] gap-5 text-2xl text-center absolute top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] w-[55%]">
                    {NavItems()}
                  </ul>
                </div>
              </DialogBody>
            </Dialog>
          );
        } else {
          // setExpandMenu(false); <--- This line is causing rerenders: Remove it!
          return <> </>;
        }

相关问题