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

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

什么是 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响应式状态创建响应式状态对象
资源下载
下载价格免费
注意:本网站资源属于虚拟产品,不支持退款。请谨慎购买! 购买后资源无法下载,请联系客服QQ:844475003,微信号:th844475003。
原文链接:https://code.ifrontend.net/archives/791,转载请注明出处。
0

评论0

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