跳到主要内容

React自定义hook

· 阅读需 3 分钟

自定义hook

// 使用自定义hook来复用代码逻辑
import { useEffect, useState } from "react";

function useWindowSize() {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
<!--truncate-->
useEffect(() => {
const handleResize = () => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
};
// 浏览器窗口发生变化时,改变windowSize
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);
// hook里面返回一个状态、函数或数组
return windowSize;
}

export default useWindowSize;
// --------------------------------------------
import { useEffect, useState } from "react";
import "./App.css";
import useWindowSize from "./hooks/useWindowSize";

function App() {
const windowSize = useWindowSize();

return (
<main className="container">
<div>
<h1>Width: {windowSize.width}</h1>
<h1>Height: {windowSize.height}</h1>
</div>
</main>
);
}

export default App;

给hook添加参数

import { useEffect, useState } from "react";

function useWindowSize(throttleDuration = 100) {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});

useEffect(() => {
let timeoutId = null;
const handleResize = () => {
if (!timeoutId) {
timeoutId = setTimeout(() => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
timeoutId = null;
}, throttleDuration);
}
};

window.addEventListener("resize", handleResize);
return () => {
clearInterval(timeoutId);
window.removeEventListener("resize", handleResize);
};
}, [throttleDuration]);

return windowSize;
}

export default useWindowSize;

多个hook联用

import { useState, useEffect } from "react";

const breakpoints = [
{ name: "mobile", width: 480 },
{ name: "tablet", width: 768 },
{ name: "laptop", width: 1024 },
{ name: "desktop", width: 1440 },
];

function useBreakpoint(windowWidth) {
const initialBreakPoint = breakpoints.find(
(breakpoint) => windowWidth <= breakpoint.width
);

const [currentBreakpoint, setCurrentBreakpoint] = useState(
initialBreakPoint?.name || "unknown"
);

useEffect(() => {
for (const breakpoint of breakpoints) {
if (windowWidth <= breakpoint.width) {
setCurrentBreakpoint(breakpoint.name);
break;
}
}
}, [windowWidth]);

return currentBreakpoint;
}

export default useBreakpoint;

import "./App.css";
import ResponsiveContent from "./components/ResponsiveContent";
import useWindowSize from "./hooks/useWindowSize";
import useBreakpoint from "./hooks/useBreakPoint";

function App() {
const windowSize = useWindowSize(500);
const breakpoint = useBreakpoint(windowSize.width);
// breakpoint的值会随着windowSize.width的值改变而改变
// 说明前面hook的返回值会变化,那么后面hook的参数也会跟着变化

return (
<main className="container">
<div>
<h1>Width: {windowSize.width}</h1>
<h1>Height: {windowSize.height}</h1>
<h1>Break Point: {breakpoint}</h1>
</div>
<ResponsiveContent />
</main>
);
}

export default App;