我正在创建一个自定义钩子,用于捕获浏览器窗口大小,让我知道它是否是移动的。目前,我的问题是 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;
}
答案 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
钩子的默认值上调用它以节省重新在钩子第一次加载时立即渲染。