用于调整窗口大小的自定义钩子

时间:2021-03-11 18:24:30

标签: reactjs react-hooks

我正在创建一个自定义钩子,用于捕获浏览器窗口大小,让我知道它是否是移动的。目前,我的问题是 React 告诉我它不能在 useEffect 钩子中保留 screenSize 的变量值。我该如何解决这个问题?

export default function useIsMobile() {
    let screenSize = 0;
    useEffect(() => {
        window.addEventListener("resize", () => {
            screenSize = window.innerWidth;
        });
        return () => {
            window.removeEventListener("resize", () => {
                screenSize = window.innerWidth;
            })
        }
    }, [screenSize]);
    
    return screenSize <= 768;
}

1 个答案:

答案 0 :(得分:2)

您可以使用 useRef 挂钩在组件级别创建变量,然后使用 .current 属性更新其值。

export default function useIsMobile() {
    const screenSize = useRef();

    useEffect(() => {
        window.addEventListener("resize", () => {
            screenSize.current = window.innerWidth;
        });
        return () => {
            window.removeEventListener("resize", () => {
                screenSize.current = window.innerWidth;
            })
        }
    }, []);
    
    return screenSize.current <= 768;
}

请注意,我还从 useEffect 钩子中删除了依赖项,因为它不需要。因为它是一个引用而不是一个状态,所以你每次都会使用相同的变量,这意味着你不需要重新注册监听器。

更新

useRef 的工作方式不会触发重新渲染,这就是为什么需要使用 useState 钩子的原因。 每次模式更改时,此代码段都会导致重新渲染。


const getIsMobile = () => window.innerWidth <= 768;

export default function useIsMobile() {
    const [isMobile, setIsMobile] = useState(getIsMobile());

    useEffect(() => {
        const onResize = () => {
            setIsMobile(getIsMobile());
        }

        window.addEventListener("resize", onResize);
    
        return () => {
            window.removeEventListener("resize", onResize);
        }
    }, []);
    
    return isMobile;
}

请注意,我将 getIsMobile 移到了组件之外,因为它不包含任何与其相关的逻辑,因此可以在 useState 钩子的默认值上调用它以节省重新在钩子第一次加载时立即渲染。