如何正确编写取决于值的自定义反应挂钩?

How to properly write a custom react hook which depends on a value?

我的钩子的目标是确定菜单的"open direction"。 当高度不够时,打开方向将从"bottom"切换到"top"。 我将我的代码简化为一个虚拟示例以便能够对其进行演示。 你可以在我添加的动画gif中看到它。

那么,我的问题是什么? 在我的真实代码中,"open direction" 的逻辑取决于 来自状态的最后一个 "openDirection" 。 使用我习惯的 类,效果很好,我添加了使用 类 的代码示例。 在 handleResize 中,我将当前的 openDirection 写入控制台,以模拟在我的真实代码中使用它。

BUT 在我的钩子代码示例中,您可以看到每次我从 handleResize 写入控制台时,openDirection 始终是状态的第一个初始值,即底部。

我猜它是这样工作的,因为我提供了 [] 依赖性,所以 useLayoutEffect 只在第一次工作。但是我该怎么办?如果我将 openDirection 作为依赖项传递,它将起作用,但这意味着每次 addEventListener 都会被添加, removeEventListener 将被删除,对于每个调整大小事件!

我真的很迷茫,我该怎么办?

import { useLayoutEffect, useState } from 'react';

const useOpenDirection = () => {
  const [openDirection, setOpenDirection] = useState("bottom");

  useLayoutEffect(() => {
    const handleResize = () => {
      console.log('openDirection', openDirection);
      if (window.innerHeight < 622) {
        setOpenDirection("top");
      } else {
        setOpenDirection("bottom");
      }
    }

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

  return openDirection;
};

export default useOpenDirection;

实时编辑完整代码:

classes code example

hooks code example

您的 openDirection 已成为陈旧的闭包,因为依赖项为空数组。如果您使用功能更新,您可以访问 openDirection 的当前值:

useLayoutEffect(() => {
    const handleResize = () => {

        setOpenDirection(current => {
            // If you need you can also use current to compute return value of this function
            if (window.innerHeight < 622) {
                console.log('openDirection', current);
                return "top";
            } else {
                console.log('openDirection', current);
                return "bottom";
            }

        });

    }

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