使用 `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;
现在要确定屏幕尺寸,我们首先要检查客户端是否是浏览器,方法是检查我们是否可以访问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;
您可以在组件中使用此钩子,如下所示,
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>
);
}
然而,当窗口大小调整时,这个钩子不会通知我们大小的变化(如上图所示)。为了实现这一点,我们必须在监听器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;
现在,如果我们想要断点而不是绝对宽度,我们可以使用一个简单的实用函数将尺寸转换为特定的断点(比如说sm
,,,)md
。lg
xlg
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;
最终代码的codesandbox如下
祝愿您的用户在所有尺寸的设备上都能满意!😄
封面照片由Hal Gatewood在Unsplash上拍摄
鏂囩珷鏉ユ簮锛�https://dev.to/3sanket3/usewindowsize-react-hook-to-handle-responsiveness-in-javascript-3dcl