所有分类
  • 所有分类
  • Html5资源
  • React资源
  • Vue资源
  • Php资源
  • ‌小程序资源
  • Python资源

React强大且灵活hooks库——ahooks入门实践之生命周期类hook(lifecycle)详解

什么是 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,用于判断组件是否已经卸载,避免在组件卸载后执行异步操作
资源下载
下载价格免费
注意:本网站资源属于虚拟产品,不支持退款。请谨慎购买! 购买后资源无法下载,请联系客服QQ:844475003,微信号:th844475003。
原文链接:https://code.ifrontend.net/archives/783,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?