我不知道我是否没有理解 useCallBack 的用途,或者我是否做错了什么。
我有一个钩子来确定我是在台式机、平板电脑还是移动设备上,它会监听屏幕的宽度。这很好用。
现在我有一个组件需要计算某些东西的高度,我只需要在移动设备中执行此操作,并且我正在监听窗口大小调整,以防某些文本中断和高度增加。
但是在我的组件中的
handleWindowSizeChange
函数中,isDesktop 始终具有初始值。甚至使用 useCallBack
钩子。
这是我的代码:
const handleWindowSizeChange = useCallback(() => {
console.log(isDesktop) // if I start in desktop it's always true, if I start in mobile it's always false.
}, [isDesktop]);
useEffect(() => {
console.log(isDesktop) //This triggers when you hit the breakpoint with the correct value
}, [isDesktop]);
useEffect(() => {
if (!loaded) return;
handleWindowSizeChange();
window.addEventListener('resize', handleWindowSizeChange);
return () => {
window.removeEventListener('resize', handleWindowSizeChange);
}
}, [loaded]);
这是我的钩子(丑陋但有效):
'use client'
import { useState, useEffect } from 'react';
import { throttle } from './utils';
export default function useDeviceDetect() {
const [isMobile, setMobile] = useState(false);
const [isTablet, setTablet] = useState(false);
const [isDesktop, setDesktop] = useState(false);
const [loaded, setLoaded] = useState(false);
const breakpointSmall = 480;
const breakpointMedium = 960;
const breakpointLarge = 1280;
const breakpointXLarge = 1680;
function handleWindowSizeChange() {
if (window.screen.width < breakpointSmall) {
setMobile(true);
setTablet(false);
setDesktop(false);
}
if (window.screen.width >= breakpointSmall && window.screen.width < breakpointMedium) {
setMobile(false);
setTablet(true);
setDesktop(false);
}
if (window.screen.width >= breakpointMedium && window.screen.width < breakpointLarge) {
setMobile(false);
setTablet(false);
setDesktop(true);
}
if (window.screen.width >= breakpointLarge && window.screen.width < breakpointXLarge) {
setMobile(false);
setTablet(false);
setDesktop(true);
}
if (window.screen.width >= breakpointXLarge) {
setMobile(false);
setTablet(false);
setDesktop(true);
}
setLoaded(true);
}
useEffect(() => {
handleWindowSizeChange();
window.addEventListener('resize', handleWindowSizeChange);
return () => {
window.removeEventListener('resize', handleWindowSizeChange);
}
}, []);
return { isMobile, isTablet, isDesktop, loaded };
}
如果我理解正确,
useCallBack
会缓存该函数并在依赖项发生变化时重建它。
我认为这个钩子是为了“修复错误”,例如在 setInterval
中状态没有更新。
我做错了什么还是我没有理解这个钩子?
使用
window.innerWidth
代替 window.screen.width
。
"use client"
import { useState, useEffect, useCallback } from "react"
export default function useDeviceDetect() {
const [device, setDevice] = useState({
isMobile: false,
isTablet: false,
isDesktop: false,
loaded: false,
})
const breakpoints = { small: 480, medium: 960, large: 1280, xLarge: 1680 }
const handleWindowSizeChange = useCallback(() => {
// Use window.innerWidth (not window.screen.width)
const width = window.innerWidth
setDevice({
isMobile: width < breakpoints.small,
isTablet: width >= breakpoints.small && width < breakpoints.medium,
isDesktop: width >= breakpoints.medium,
loaded: true,
})
}, [breakpoints.medium, breakpoints.small])
useEffect(() => {
handleWindowSizeChange()
window.addEventListener("resize", handleWindowSizeChange)
return () => window.removeEventListener("resize", handleWindowSizeChange)
}, [handleWindowSizeChange])
return device
}