如何在 React 中检测屏幕尺寸是不是已更改为移动设备?

Posted

技术标签:

【中文标题】如何在 React 中检测屏幕尺寸是不是已更改为移动设备?【英文标题】:How to detect if screen size has changed to mobile in React?如何在 React 中检测屏幕尺寸是否已更改为移动设备? 【发布时间】:2017-11-12 18:51:18 【问题描述】:

我正在使用 React 开发一个 Web 应用程序,需要检测屏幕尺寸何时进入移动断点以更改状态。

具体来说,当用户进入移动模式时,我需要折叠我的 sidenav,并通过存储在组件内的状态中的布尔值进行控制。

【问题讨论】:

【参考方案1】:

我所做的是在组件挂载后添加一个事件监听器:

componentDidMount() 
    window.addEventListener("resize", this.resize.bind(this));
    this.resize();


resize() 
    this.setState(hideNav: window.innerWidth <= 760);


componentWillUnmount() 
    window.removeEventListener("resize", this.resize.bind(this));

编辑: 为了保存状态更新,我稍微改变了“resize”,只在窗口宽度发生变化时才更新。

resize() 
    let currentHideNav = (window.innerWidth <= 760);
    if (currentHideNav !== this.state.hideNav) 
        this.setState(hideNav: currentHideNav);
    

更新:是时候使用钩子了! 如果您的组件是功能性的,并且您使用挂钩 - 那么您可以使用来自 react-responsive 包的 useMediaQuery 挂钩。

import  useMediaQuery  from 'react-responsive';

...

const isMobile = useMediaQuery( query: `(max-width: 760px)` );

使用此钩子后,“isMobile”将在屏幕调整大小时更新,并重新渲染组件。好多了!

【讨论】:

您需要去抖动或限制该事件侦听器。您将找到here 的示例。【参考方案2】:

这与@Ben Cohen answer 相同,但在将您的函数附加到 eventListner 后,还要在 componentWillUnmount

上将其删除
constructor() 
  super();
  this.state =  screenWidth: null ;
  this.updateWindowDimensions = this.updateWindowDimensions.bind(this);


componentDidMount() 
    window.addEventListener("resize", this.updateWindowDimensions());


componentWillUnmount() 
    window.removeEventListener("resize", this.updateWindowDimensions)


updateWindowDimensions() 
   this.setState( screenWidth: window.innerWidth );

【讨论】:

这是正确答案,应该这样标记。 (它也应该被去抖动或节流,正如 ivarni 对上述答案的评论。) 在调用 addEventListener 时,它应该只传递 this.updateWindowDimensions 引用而不是调用它。【参考方案3】:

在 React(16.8.0+) 中使用 hooks 指的是: https://***.com/a/36862446/1075499

import  useState, useEffect  from 'react';

function getWindowDimensions() 
  const  innerWidth: width, innerHeight: height  = window;
  return 
    width,
    height
  ;


export default function useWindowDimensions() 
  const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());

  useEffect(() => 
    function handleResize() 
      setWindowDimensions(getWindowDimensions());
    

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

  return windowDimensions;

【讨论】:

这是另一个答案的复制粘贴:***.com/a/36862446/1075499 不属于自己的解决方案请参考参考【参考方案4】:
const [isMobile, setIsMobile] = useState(false)
 
//choose the screen size 
const handleResize = () => 
  if (window.innerWidth < 720) 
      setIsMobile(true)
   else 
      setIsMobile(false)
  


// create an event listener
useEffect(() => 
  window.addEventListener("resize", handleResize)
)

// finally you can render components conditionally if isMobile is True or False 

【讨论】:

【参考方案5】:

嘿,我刚刚为这个问题发布了一个 npm 包。 看看https://www.npmjs.com/package/react-getscreen

import React,  Component  from 'react';
import withGetScreen from 'react-getscreen'

class Test extends Component 
  render() 
    if (this.props.isMobile()) return <div>Mobile</div>;
    if (this.props.isTablet()) return <div>Tablet</div>;
    return <div>Desktop</div>;
  


export default withGetScreen(Test);

//or you may set your own breakpoints by providing an options object

const options = mobileLimit: 500, tabletLimit: 800
export default withGetScreen(Test, options);

【讨论】:

如果你问我,浏览器应该更容易获得物理屏幕尺寸而不仅仅是分辨率,因为像素密度变化很大...... 根据我的经验,根据屏幕尺寸布置的组件的可重用性较低,因为例如,如果您将它们放在 2 x 2 网格中,它们将呈现为整个屏幕而不是四分之一。 嗯,像这样的插件,只能用在容器组件之类的东西上 是的,他们适合这种情况 在func组件中如何使用?【参考方案6】:

有多种存档方式,第一种方式是使用 CSS 使用此类

@media screen and (max-width: 576px) 

此标签内的任何类只有在屏幕等于或小于 576px 时才可见

第二种方式是使用事件监听器

类似的东西

 constructor(props)
    
        super(props);

        this.state = 
            isToggle: null
        

        this.resizeScreen = this.resizeScreen.bind(this); 
    
    
    
     componentDidMount() 

        window.addEventListener("resize", this.resizeScreen());

    
    
    
    resizeScreen() 
        if(window.innerWidth === 576)
        
            this.setState(isToggle:'I was resized');
        
        
    

即使使用事件监听器,我仍然更喜欢 CSS 方式,因为我们可以使用多种屏幕尺寸而无需进一步的 js 编码。

我希望这会有所帮助!

【讨论】:

【参考方案7】:

react-screentype-hook 库允许您开箱即用地执行此操作。 https://www.npmjs.com/package/react-screentype-hook

您可以使用它提供的默认断点,如下所示

const screenType = useScreenType();

screenType 具有以下形状

  
    isLargeDesktop: Boolean,
    isDesktop: Boolean,
    isMobile: Boolean,
    isTablet: Boolean
  

或者你甚至可以像这样配置你的自定义断点

const screenType = useScreenType(
    mobile: 400,
    tablet: 800,
    desktop: 1000,
    largeDesktop: 1600
  );

【讨论】:

【参考方案8】:

在Functional Component中,我们可以通过useTheme和useMediaQuery来检测屏幕大小。 常量主题 = useTheme(); const xs = useMediaQuery(theme.breakpoints.only('xs')); const sm = useMediaQuery(theme.breakpoints.only('sm')); const md = useMediaQuery(theme.breakpoints.only('md')); const lg = useMediaQuery(theme.breakpoints.only('lg')); const xl = useMediaQuery(theme.breakpoints.only('xl'));

【讨论】:

以上是关于如何在 React 中检测屏幕尺寸是不是已更改为移动设备?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 xcode4.3 中获取和修改显示屏幕尺寸

如何在OpenGL中自动选择屏幕尺寸

所有警报对话框消息和textField都已更改为单行。请检查图像

如何仅针对特定屏幕尺寸缩小字体

故事板iOS - 如何以屏幕尺寸的百分比而不是静态值顶部引脚边距给出上边距?

检测屏幕高度并裁剪全尺寸图像