React强大且灵活hooks库——ahooks入门实践之高级类hook(advanced)详解

发布于:2025-07-17 ⋅ 阅读:(12) ⋅ 点赞:(0)

什么是 ahooks?

ahooks 是一个 React Hooks 库,提供了大量实用的自定义 hooks,帮助开发者更高效地构建 React 应用。其中高级类 hooks 是 ahooks 的一个重要分类,专门用于处理一些高级场景,如受控值、事件发射器、性能优化等。

安装 ahooks

npm install ahooks

高级类 hooks 详解

useControllableValue – 受控值

useControllableValue 用于处理受控和非受控组件的值管理。

import React, { useState } from "react";
import { useControllableValue } from "ahooks";
import { Card, Input, Button, Switch } from "antd";

const UseControllableValueExample = () => {
  const [controlled, setControlled] = useState(false);
  const [value, setValue] = useControllableValue({
    value: controlled ? "受控值" : undefined,
    defaultValue: "默认值",
    onChange: (val) => {
      console.log("值变化:", val);
    },
  });

  return (
    <Card title="useControllableValue 受控值">
      <div style={{ marginBottom: 16 }}>
        <p>
          <strong>当前值:</strong> {value}
        </p>
        <p>
          <strong>模式:</strong> {controlled ? "受控" : "非受控"}
        </p>
      </div>

      <div style={{ marginBottom: 16 }}>
        <Input
          value={value}
          onChange={(e) => setValue(e.target.value)}
          placeholder="输入内容"
          style={{ marginBottom: 8 }}
        />
        <Switch
          checked={controlled}
          onChange={setControlled}
          checkedChildren="受控"
          unCheckedChildren="非受控"
        />
      </div>

      <Button onClick={() => setValue("重置值")}>重置</Button>
    </Card>
  );
};

useCreation – 创建值

useCreation 用于创建值,类似于 useMemo,但更稳定。

import React, { useState } from "react";
import { useCreation } from "ahooks";
import { Card, Button } from "antd";

const UseCreationExample = () => {
  const [count, setCount] = useState(0);

  // 使用 useCreation 创建稳定的对象
  const stableObject = useCreation(() => {
    return {
      id: Math.random(),
      timestamp: Date.now(),
    };
  }, []);

  // 使用 useCreation 创建计算值
  const expensiveValue = useCreation(() => {
    console.log("计算昂贵值");
    return count * 2 + 10;
  }, [count]);

  return (
    <Card title="useCreation 创建值">
      <div style={{ marginBottom: 16 }}>
        <p>
          <strong>计数:</strong> {count}
        </p>
        <p>
          <strong>计算值:</strong> {expensiveValue}
        </p>
        <p>
          <strong>稳定对象 ID:</strong> {stableObject.id}
        </p>
        <p>
          <strong>稳定对象时间戳:</strong> {stableObject.timestamp}
        </p>
      </div>

      <Button onClick={() => setCount(count + 1)}>增加计数</Button>
    </Card>
  );
};

useEventEmitter – 事件发射器

useEventEmitter 用于创建事件发射器,实现组件间通信。

import React, { useRef } from "react";
import { useEventEmitter } from "ahooks";
import { Card, Button, Input } from "antd";

const UseEventEmitterExample = () => {
  const eventEmitter = useEventEmitter();

  const handleEmit = () => {
    eventEmitter.emit();
  };

  return (
    <Card title="useEventEmitter 事件发射器">
      <div style={{ marginBottom: 16 }}>
        <p>点击按钮发射事件,输入框会自动获得焦点</p>
      </div>

      <Button onClick={handleEmit} style={{ marginBottom: 16 }}>
        发射事件
      </Button>

      <InputBox eventEmitter={eventEmitter} />
    </Card>
  );
};

// 输入框组件
const InputBox = ({ eventEmitter }) => {
  const inputRef = useRef(null);

  eventEmitter.useSubscription(() => {
    inputRef.current?.focus();
  });

  return (
    <Input
      ref={inputRef}
      placeholder="输入框会自动获得焦点"
      style={{ width: "100%" }}
    />
  );
};

export default UseEventEmitterExample;

useIsomorphicLayoutEffect – 同构布局副作用

useIsomorphicLayoutEffect 在服务端渲染时使用 useEffect,在客户端使用 useLayoutEffect

import React, { useState, useRef } from "react";
import { useIsomorphicLayoutEffect } from "ahooks";
import { Card, Button } from "antd";

const UseIsomorphicLayoutEffectExample = () => {
  const [count, setCount] = useState(0);
  const ref = useRef(null);

  useIsomorphicLayoutEffect(() => {
    if (ref.current) {
      // 在布局更新前同步执行
      ref.current.style.backgroundColor =
        count % 2 === 0 ? "#f0f0f0" : "#e6f7ff";
    }
  }, [count]);

  return (
    <Card title="useIsomorphicLayoutEffect 同构布局副作用">
      <div style={{ marginBottom: 16 }}>
        <p>
          <strong>计数:</strong> {count}
        </p>
      </div>

      <div
        ref={ref}
        style={{
          padding: 16,
          border: "1px solid #d9d9d9",
          borderRadius: 4,
          transition: "background-color 0.3s",
        }}
      >
        这个div的背景色会在布局更新前同步改变
      </div>

      <Button onClick={() => setCount(count + 1)} style={{ marginTop: 16 }}>
        切换背景色
      </Button>
    </Card>
  );
};

useLatest – 最新值

useLatest 返回一个 ref,始终指向最新的值。

import React, { useState, useEffect } from "react";
import { useLatest } from "ahooks";
import { Card, Button } from "antd";

const UseLatestExample = () => {
  const [count, setCount] = useState(0);
  const latestCount = useLatest(count);

  useEffect(() => {
    const timer = setInterval(() => {
      console.log("当前值:", count);
      console.log("最新值:", latestCount.current);
    }, 1000);

    return () => clearInterval(timer);
  }, []);

  return (
    <Card title="useLatest 最新值">
      <div style={{ marginBottom: 16 }}>
        <p>
          <strong>当前值:</strong> {count}
        </p>
        <p>
          <strong>最新值引用:</strong> {latestCount.current}
        </p>
        <p style={{ fontSize: "12px", color: "#666" }}>
          每秒在控制台输出当前值和最新值引用
        </p>
      </div>

      <Button onClick={() => setCount(count + 1)}>增加计数</Button>
    </Card>
  );
};

useMemoizedFn – 记忆化函数

useMemoizedFn 用于创建记忆化的函数,避免不必要的重新渲染。

import React, { useState } from "react";
import { useMemoizedFn } from "ahooks";
import { Card, Button } from "antd";

const UseMemoizedFnExample = () => {
  const [count, setCount] = useState(0);
  const [renderCount, setRenderCount] = useState(0);

  // 使用 useMemoizedFn 创建稳定的函数
  const handleClick = useMemoizedFn(() => {
    setCount(count + 1);
    console.log("点击处理函数执行");
  });

  // 每次渲染都会创建新函数
  const handleClickNormal = () => {
    setCount(count + 1);
    console.log("普通函数执行");
  };

  // 强制重新渲染
  const forceRender = () => {
    setRenderCount(renderCount + 1);
  };

  return (
    <Card title="useMemoizedFn 记忆化函数">
      <div style={{ marginBottom: 16 }}>
        <p>
          <strong>计数:</strong> {count}
        </p>
        <p>
          <strong>渲染次数:</strong> {renderCount}
        </p>
      </div>

      <div style={{ marginBottom: 16 }}>
        <Button onClick={handleClick} style={{ marginRight: 8 }}>
          记忆化函数
        </Button>
        <Button onClick={handleClickNormal} style={{ marginRight: 8 }}>
          普通函数
        </Button>
        <Button onClick={forceRender}>强制重新渲染</Button>
      </div>

      <p style={{ fontSize: "12px", color: "#666" }}>
        记忆化函数在重新渲染时保持稳定,普通函数每次都会重新创建
      </p>
    </Card>
  );
};

useReactive – 响应式状态

useReactive 用于创建响应式状态对象。

import React from "react";
import { useReactive } from "ahooks";
import { Card, Button, Input } from "antd";

const UseReactiveExample = () => {
  const state = useReactive({
    user: {
      name: "张三",
      age: 25,
    },
    count: 0,
    list: [1, 2, 3],
  });

  const handleUpdateName = () => {
    state.user.name = "李四";
  };

  const handleUpdateAge = () => {
    state.user.age += 1;
  };

  const handleAddCount = () => {
    state.count += 1;
  };

  const handleAddToList = () => {
    state.list.push(state.list.length + 1);
  };

  return (
    <Card title="useReactive 响应式状态">
      <div style={{ marginBottom: 16 }}>
        <p>
          <strong>用户名:</strong> {state.user.name}
        </p>
        <p>
          <strong>年龄:</strong> {state.user.age}
        </p>
        <p>
          <strong>计数:</strong> {state.count}
        </p>
        <p>
          <strong>列表:</strong> {state.list.join(", ")}
        </p>
      </div>

      <div style={{ marginBottom: 16 }}>
        <Input
          value={state.user.name}
          onChange={(e) => (state.user.name = e.target.value)}
          placeholder="输入用户名"
          style={{ marginBottom: 8 }}
        />
      </div>

      <div>
        <Button onClick={handleUpdateName} style={{ marginRight: 8 }}>
          更新姓名
        </Button>
        <Button onClick={handleUpdateAge} style={{ marginRight: 8 }}>
          增加年龄
        </Button>
        <Button onClick={handleAddCount} style={{ marginRight: 8 }}>
          增加计数
        </Button>
        <Button onClick={handleAddToList}>添加列表项</Button>
      </div>
    </Card>
  );
};

高级类 hooks 速查表

Hook 名称 用途 描述
useControllableValue 受控值 处理受控和非受控组件的值管理
useCreation 创建值 创建稳定的值,类似于 useMemo
useEventEmitter 事件发射器 创建事件发射器,实现组件间通信
useIsomorphicLayoutEffect 同构布局副作用 在服务端和客户端使用不同的副作用
useLatest 最新值 返回一个始终指向最新值的 ref
useMemoizedFn 记忆化函数 创建记忆化的函数,避免不必要的重新渲染
useReactive 响应式状态 创建响应式状态对象

 React强大且灵活hooks库——ahooks入门实践之高级类hook(advanced)详解 - 高质量源码分享平台-免费下载各类网站源码与模板及前沿动态资讯


网站公告

今日签到

点亮在社区的每一天
去签到