useIsMobile Hook

268 阅读1分钟

在uniswap interface中的searchBar使用了这个自定义的hook,来判断是否是mobile,

// @deprecated in favor of useScreenSize 已弃用,转到useScreenSize
import { useScreenSize } from 'hooks/useScreenSize'

export function useIsMobile(): boolean {
  const isScreenSize = useScreenSize()
  const isMobile = !isScreenSize['sm']
  return isMobile
}

所以useScreenSize这个hook是判断的核心:

import { useEffect, useState } from 'react'
//检测代码是否在浏览器环境中运行  ssr 是 global
const isClient = typeof window !== 'undefined'
不同设备的screen 界限
export const BREAKPOINTS = {
  xs: 396,
  sm: 640,
  md: 768,
  lg: 1024,
  xl: 1280,
  xxl: 1536,
  xxxl: 1920,
}
export const navSearchInputVisibleSize = 1100
const BREAKPOINTS_ADDITIONAL = {
   ...BREAKPOINTS,
   navSearchInputVisible: navSearchInputVisibleSize,// uniswap自定义了一个 BREAKPOINTS 用于特定组件
}
// 使用`Object.keys(BREAKPOINTS_ADDITIONAL).reduce`遍历断点对象的键,为每个断点创建一个对应的键值对,其值表示屏幕宽度是否大于断点值。 
function getScreenSize():Record<key as keyof typeof BREAKPOINTS_ADDITIONAL,boolean>{ 
  return Object.keys(BREAKPOINTS_ADDITIONAL).reduce(
    (obj,key)=>{
      return Object.assign(obj,{
       [key]: isClient ? window.innerWidth > BREAKPOINTS_ADDITIONAL[key as keyof typeof BREAKPOINTS_ADDITIONAL]  : false
      }
    },
    {} as Record<key as keyof typeof BREAKPOINTS_ADDITIONAL,boolean>
   )
}
export function useScreenSize(){
  const [screenSize,setScreenSize] = useState(getScreenSize())
  useEffect(()=>{
    function handleResize(){
      setScreenSize(getScreenSize())
    }
    if(isClient){
      window.addEventListener("resize",handleResize)
      return () => {
        window.removeEventListener('resize', handleResize)
       }
    }
    return undefinded;
  },[])
  return screenSize;
}

然后在通过这个hook 来自定义一些 相关的设备的函数控制 uniswap中的使用

export function useIsTablet(): boolean {
  const isScreenSize = useScreenSize()
  const isTablet = !isScreenSize['lg'] && isScreenSize['sm']
  return isTablet
}