使用 `useWindowSize` React Hook 处理 JavaScript 中的响应性

2025-06-08

使用 `useWindowSize` React Hook 处理 JavaScript 中的响应性

有时了解 JavaScript 中的响应断点以根据屏幕大小调整和运行逻辑会很有帮助。

我们将创建一个自定义 React Hook。它将确定屏幕尺寸。并且,我们将能够像在 CSS 媒体查询中一样使用屏幕尺寸来更新 UI 或使逻辑以特定方式运行。

代码依赖于window浏览器的对象。如果在服务器端渲染时该window对象不存在,则该解决方案将无法工作。

我们将自定义钩子命名为useWindowSize。我们将有一个名为 的状态变量windowSize,它将被导出以供 React 组件使用。



import { useState, useEffect } from "react";

function useWindowSize() {
  const [windowSize, setWindowSize] = useState(undefined);

  ...
  //code to determine the screen size will go here

  ...

  //expose windowSize variable to be used by Components
  // to make responsiveness related chanegs
  return windowSize;
}

export default useWindowSize;


Enter fullscreen mode Exit fullscreen mode

现在要确定屏幕尺寸,我们首先要检查客户端是否是浏览器,方法是检查我们是否可以访问window对象。如果可以,我们可以获取屏幕宽度window.innerWidth,并将其作为默认值赋给状态变量。



import { useState, useEffect } from "react";

function useWindowSize() {
  //👇
  const isWindowClient = typeof window === "object";

  const [windowSize, setWindowSize] = useState(
    isWindowClient ? window.innerWidth : undefined
  );
  //☝️

  return windowSize;
}

export default useWindowSize;


Enter fullscreen mode Exit fullscreen mode

您可以在组件中使用此钩子,如下所示,



import React from "react";
import useWindowSize from "./useWindowSize";

export default function App() {
  const windowSize = useWindowSize();
  return (
    <div>
      <h1>The screen width is: </h1>
      <span style={{ fontSize: "30px" }}>{windowSize}</span>
    </div>
  );
}


Enter fullscreen mode Exit fullscreen mode

静态宽度 gif

然而,当窗口大小调整时,这个钩子不会通知我们大小的变化(如上图所示)。为了实现这一点,我们必须在监听器window上实现resize。我们将使用它,useEffect这样我们就不会在每次渲染时都注册监听器,并确保它在需要时被注销。



import { useState, useEffect } from "react";

function useWindowSize() {
  const isWindowClient = typeof window === "object";

  const [windowSize, setWindowSize] = useState(
    isWindowClient ? window.innerWidth : undefined
  );

  //👇
  useEffect(() => {
    //a handler which will be called on change of the screen resize
    function setSize() {
      setWindowSize(window.innerWidth);
    }

    if (isWindowClient) {
      //register the window resize listener
      window.addEventListener("resize", setSize);

      //un-register the listener
      return () => window.removeEventListener("resize", setSize);
    }
  }, [isWindowClient, setWindowSize]);
  //☝️

  return windowSize;
}

export default useWindowSize;


Enter fullscreen mode Exit fullscreen mode

动态宽度 gif

现在,如果我们想要断点而不是绝对宽度,我们可以使用一个简单的实用函数将尺寸转换为特定的断点(比如说sm,,,mdlgxlg



import { useState, useEffect } from "react";

//👇
//a Util function that will conver the absolute width into breakpoints
function getBreakPoint(windowWidth) {
  if (windowWidth) {
    if (windowWidth < 480) {
      return "sm";
    } else if (windowWidth < 1024) {
      return "md";
    } else if (windowWidth < 1200) {
      return "lg";
    } else {
      return "xlg";
    }
  } else {
    return undefined;
  }
}
//☝️

function useWindowSize() {
  const isWindowClient = typeof window === "object";

  const [windowSize, setWindowSize] = useState(
    isWindowClient
      ? getBreakPoint(window.innerWidth) //👈
      : undefined
  );

  useEffect(() => {
    //a handler which will be called on change of the screen resize
    function setSize() {
      setWindowSize(getBreakPoint(window.innerWidth)); //👈
    }

    if (isWindowClient) {
      //register the window resize listener
      window.addEventListener("resize", setSize);

      //unregister the listerner on destroy of the hook
      return () => window.removeEventListener("resize", setSize);
    }
  }, [isWindowClient, setWindowSize]);

  return windowSize;
}

export default useWindowSize;


Enter fullscreen mode Exit fullscreen mode

带有断点 gif

最终代码的codesandbox如下

祝愿您的用户在所有尺寸的设备上都能满意!😄

封面照片由Hal GatewoodUnsplash上拍摄

鏂囩珷鏉ユ簮锛�https://dev.to/3sanket3/usewindowsize-react-hook-to-handle-responsiveness-in-javascript-3dcl
PREV
我在前端项目中使用的构建工具和扩展
NEXT
不再需要邮递员,只需使用 cURL + vim = 使结果更方便。