什么是 ahooks?
ahooks 是一个 React Hooks 库,提供了大量实用的自定义 hooks,帮助开发者更高效地构建 React 应用。其中生命周期类 hooks 是 ahooks 的一个重要分类,专门用于处理组件的生命周期事件。
安装 ahooks
npm install ahooks
生命周期类 hooks 详解
useMount – 组件挂载
useMount
用于在组件挂载时执行副作用操作,类似于 useEffect
的空依赖数组。
import React, { useState } from "react";
import { useMount } from "ahooks";
import { Card, Button, List, message } from "antd";
const UseMountExample = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
useMount(() => {
console.log("组件已挂载,开始初始化数据...");
fetchInitialData();
});
const fetchInitialData = async () => {
setLoading(true);
try {
// 模拟API调用
await new Promise((resolve) => setTimeout(resolve, 1000));
const mockData = [
{ id: 1, name: "张三", email: "zhangsan@example.com" },
{ id: 2, name: "李四", email: "lisi@example.com" },
{ id: 3, name: "王五", email: "wangwu@example.com" },
];
setData(mockData);
message.success("数据加载完成");
} catch (error) {
message.error("数据加载失败");
console.error("数据加载错误:", error);
} finally {
setLoading(false);
}
};
const handleRefresh = () => {
fetchInitialData();
};
return (
<div>
<Card title="useMount 组件挂载示例" style={{ marginBottom: 16 }}>
<div style={{ marginBottom: 16 }}>
<Button type="primary" onClick={handleRefresh} loading={loading}>
刷新数据
</Button>
<span style={{ marginLeft: 8, color: "#666" }}>
组件挂载时会自动加载数据
</span>
</div>
<List
loading={loading}
dataSource={data}
renderItem={(item) => (
<List.Item>
<List.Item.Meta title={item.name} description={item.email} />
</List.Item>
)}
/>
</Card>
<Card title="useMount 使用场景" size="small">
<ul>
<li>组件初始化时获取数据</li>
<li>设置全局事件监听器</li>
<li>初始化第三方库</li>
<li>执行一次性的副作用操作</li>
</ul>
</Card>
</div>
);
};
export default UseMountExample;
useUnmount – 组件卸载
useUnmount
用于在组件卸载时执行清理操作,类似于 useEffect
的清理函数。
import React, { useState } from "react";
import { useUnmount } from "ahooks";
import { Card, Button, message, Alert } from "antd";
const UseUnmountExample = () => {
const [isVisible, setIsVisible] = useState(true);
const [eventCount, setEventCount] = useState(0);
// 模拟全局事件监听器
const handleGlobalClick = () => {
setEventCount((prev) => prev + 1);
};
// 组件卸载时清理事件监听器
useUnmount(() => {
console.log("组件即将卸载,清理事件监听器...");
document.removeEventListener("click", handleGlobalClick);
message.info("组件已卸载,事件监听器已清理");
});
// 添加事件监听器
React.useEffect(() => {
document.addEventListener("click", handleGlobalClick);
console.log("事件监听器已添加");
}, []);
const handleToggleVisibility = () => {
setIsVisible(!isVisible);
};
return (
<div>
<Card title="useUnmount 组件卸载示例" style={{ marginBottom: 16 }}>
<div style={{ marginBottom: 16 }}>
<Button type="primary" onClick={handleToggleVisibility}>
{isVisible ? "隐藏组件" : "显示组件"}
</Button>
</div>
{isVisible && (
<div>
<Alert
message="组件已挂载"
description="点击页面任意位置会增加计数,组件卸载时会清理事件监听器"
type="success"
showIcon
style={{ marginBottom: 16 }}
/>
<Card title="事件统计" size="small">
<p>
<strong>全局点击次数:</strong> {eventCount}
</p>
<p style={{ color: "#666", fontSize: "12px" }}>
点击"隐藏组件"按钮来触发组件卸载,观察控制台输出
</p>
</Card>
</div>
)}
</Card>
<Card title="useUnmount 使用场景" size="small">
<ul>
<li>清理事件监听器</li>
<li>取消网络请求</li>
<li>清理定时器</li>
<li>保存用户数据</li>
<li>清理第三方库实例</li>
</ul>
</Card>
</div>
);
};
export default UseUnmountExample;
useUnmountedRef – 组件卸载状态引用
useUnmountedRef
返回一个 ref,用于判断组件是否已经卸载,避免在组件卸载后执行异步操作。
import React, { useState } from "react";
import { useUnmountedRef } from "ahooks";
import { Card, Button, List, message, Tag } from "antd";
const UseUnmountedRefExample = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [requestCount, setRequestCount] = useState(0);
const unmountedRef = useUnmountedRef();
const fetchData = async (requestId) => {
setLoading(true);
setRequestCount((prev) => prev + 1);
try {
// 模拟异步请求
await new Promise((resolve) => setTimeout(resolve, 2000));
// 检查组件是否已卸载
if (unmountedRef.current) {
console.log(`请求 ${requestId} 完成,但组件已卸载,不更新状态`);
return;
}
const mockData = Array.from({ length: 5 }, (_, index) => ({
id: Date.now() + index,
name: `用户 ${requestId}-${index + 1}`,
email: `user${requestId}-${index + 1}@example.com`,
timestamp: new Date().toLocaleTimeString(),
}));
setData(mockData);
message.success(`请求 ${requestId} 完成`);
console.log(`请求 ${requestId} 完成,组件状态已更新`);
} catch (error) {
if (!unmountedRef.current) {
message.error(`请求 ${requestId} 失败`);
console.error(`请求 ${requestId} 错误:`, error);
}
} finally {
if (!unmountedRef.current) {
setLoading(false);
}
}
};
const handleStartRequest = () => {
const requestId = Date.now();
fetchData(requestId);
};
const handleUnmount = () => {
// 模拟组件卸载
console.log("模拟组件卸载...");
// 在实际应用中,这里会触发组件的卸载
};
return (
<div>
<Card
title="useUnmountedRef 卸载状态检测示例"
style={{ marginBottom: 16 }}
>
<div style={{ marginBottom: 16 }}>
<Button
type="primary"
onClick={handleStartRequest}
loading={loading}
style={{ marginRight: 8 }}
>
发起异步请求
</Button>
<Button onClick={handleUnmount}>模拟卸载</Button>
</div>
<div style={{ marginBottom: 16 }}>
<Tag color="blue">请求次数: {requestCount}</Tag>
<Tag color={loading ? "orange" : "green"}>
状态: {loading ? "加载中" : "空闲"}
</Tag>
</div>
<List
dataSource={data}
renderItem={(item) => (
<List.Item>
<List.Item.Meta
title={item.name}
description={
<div>
<div>{item.email}</div>
<div style={{ fontSize: "12px", color: "#666" }}>
创建时间: {item.timestamp}
</div>
</div>
}
/>
</List.Item>
)}
/>
</Card>
<Card
title="useUnmountedRef 使用场景"
size="small"
style={{ marginBottom: 16 }}
>
<ul>
<li>防止内存泄漏</li>
<li>避免在组件卸载后更新状态</li>
<li>取消异步操作</li>
<li>清理定时器</li>
<li>处理竞态条件</li>
</ul>
</Card>
</div>
);
};
export default UseUnmountedRefExample;
生命周期类 hooks 速查表
Hook 名称 | 用途 | 描述 |
---|---|---|
useMount | 组件挂载 | 在组件挂载时执行副作用操作,类似于 useEffect 的空依赖数组 |
useUnmount | 组件卸载 | 在组件卸载时执行清理操作,类似于 useEffect 的清理函数 |
useUnmountedRef | 卸载状态检测 | 返回一个 ref,用于判断组件是否已经卸载,避免在组件卸载后执行异步操作 |
原文链接:https://code.ifrontend.net/archives/783,转载请注明出处。
评论0