React强大且灵活hooks库——ahooks入门实践之场景类(scene)hook详解

什么是 ahooks?

ahooks 是一个 React Hooks 库,提供了大量实用的自定义 hooks,帮助开发者更高效地构建 React 应用。其中场景类 hooks 是 ahooks 的一个重要分类,专门针对特定业务场景提供解决方案。

安装 ahooks

npm install ahooks

场景类 hook 详解

useAntdTable – Antd 表格集成

useAntdTable用于处理表格与表单的联动场景。

import React from "react";
import { useAntdTable } from "ahooks";
import { Form, Input, Button, Table } from "antd";const UserTable = () => {const [form] = Form.useForm();const { tableProps, search } = useAntdTable(async (params, form) => {const { current, pageSize } = params;const response = await fetch("/api/users", {method: "POST",body: JSON.stringify({page: current,size: pageSize,...form,}),});const data = await response.json();return {list: data.list,total: data.total,};},{form,defaultPageSize: 10,});return (<div className="container m-4"><Form form={form} layout="inline" className="mb-2"><Form.Item name="name" label="姓名"><Input placeholder="请输入姓名" /></Form.Item><Form.Item name="email" label="邮箱"><Input placeholder="请输入邮箱" /></Form.Item><Form.Item><Button type="primary" onClick={search.submit}>搜索</Button><Button onClick={search.reset} style={{ marginLeft: 8 }}>重置</Button></Form.Item></Form><Table{...tableProps}columns={[{ title: "姓名", dataIndex: "name" },{ title: "邮箱", dataIndex: "email" },{ title: "创建时间", dataIndex: "createTime" },]}/></div>);
};

useFusionTable – Fusion 表格集成

useFusionTable用于处理表格与表单的联动场景。

import React from "react";
import { useFusionTable } from "ahooks";
import { Table, Button, Input } from "@alifd/next";const UserTable = () => {const { tableProps, search, loading } = useFusionTable(async (params) => {const { current, pageSize, ...rest } = params;const response = await fetch("/api/users", {method: "POST",headers: { "Content-Type": "application/json" },body: JSON.stringify({page: current,size: pageSize,...rest,}),});const data = await response.json();return {list: data.list,total: data.total,};},{defaultPageSize: 10,defaultParams: [{ current: 1, pageSize: 10 }],});return (<div><div style={{ marginBottom: 16 }}><Inputplaceholder="搜索用户名"onChange={(value) => search.setFieldValue("name", value)}style={{ width: 200, marginRight: 8 }}/><Button type="primary" onClick={search.submit}>搜索</Button><Button onClick={search.reset} style={{ marginLeft: 8 }}>重置</Button></div><Table {...tableProps} loading={loading}><Table.Column title="姓名" dataIndex="name" /><Table.Column title="邮箱" dataIndex="email" /><Table.Column title="创建时间" dataIndex="createTime" /></Table></div>);
};

useInfiniteScroll – 无限滚动

import React from "react";
import { useInfiniteScroll } from "ahooks";const InfiniteList = () => {const { data, loading, noMore } = useInfiniteScroll(async (d) => {const { list = [], total = 0 } = await fetchData(d?.list?.length || 0);return {list: [...(d?.list || []), ...list],total,};},{target: document,isNoMore: (d) => d?.list?.length >= d?.total,threshold: 100,});return (<div style={{ height: "100vh", overflow: "auto" }}>{data?.list?.map((item, index) => (<divkey={`${item.id}-${index}`}style={{padding: "12px",borderBottom: "1px solid #eee",backgroundColor: index % 2 === 0 ? "#f9f9f9" : "white",}}><h3>{item.title}</h3><p>{item.description}</p></div>))}{loading && (<div style={{ textAlign: "center", padding: "20px" }}>加载中...</div>)}{noMore && (<div style={{ textAlign: "center", padding: "20px", color: "#999" }}>没有更多数据了</div>)}</div>);
};// 模拟数据获取函数
const fetchData = async (offset = 0) => {// 模拟API调用await new Promise((resolve) => setTimeout(resolve, 1000));const pageSize = 10;const mockData = Array.from({ length: pageSize }, (_, i) => ({id: offset + i,title: `项目 ${offset + i + 1}`,description: `这是第 ${offset + i + 1} 个项目的描述`,}));return {list: mockData,total: 50, // 总共50条数据};
};export default InfiniteList;

usePagination – 分页管理

import React from "react";
import { usePagination } from "ahooks";
import { Button, Input } from "antd";const PaginationExample = () => {const { data, loading, pagination, run } = usePagination(async ({ current, pageSize }) => {const response = await fetch(`/api/users?page=${current}&size=${pageSize}`);return response.json();},{defaultPageSize: 5,defaultCurrent: 1,});const [searchValue, setSearchValue] = React.useState("");const handleSearch = () => {run({ current: 1, pageSize: pagination.pageSize, search: searchValue });};return (<div><div style={{ marginBottom: 16 }}><Inputplaceholder="搜索用户"value={searchValue}onChange={(e) => setSearchValue(e.target.value)}style={{ width: 200, marginRight: 8 }}onPressEnter={handleSearch}/><Button type="primary" onClick={handleSearch}>搜索</Button></div>{loading ? (<div>加载中...</div>) : (<div>{data?.list?.map((user) => (<divkey={user.id}style={{padding: "8px",border: "1px solid #ddd",marginBottom: "8px",}}><strong>{user.name}</strong> - {user.email}</div>))}<div style={{ marginTop: 16 }}><Buttondisabled={pagination.current === 1}onClick={() => pagination.changeCurrent(pagination.current - 1)}>上一页</Button><span style={{ margin: "0 16px" }}>第 {pagination.current} 页,共 {pagination.total} 条</span><Buttondisabled={pagination.current >= pagination.totalPages}onClick={() => pagination.changeCurrent(pagination.current + 1)}>下一页</Button></div></div>)}</div>);
};

useDynamicList – 动态列表

import React from "react";
import { useDynamicList } from "ahooks";
import { Button, Input, Card } from "antd";const DynamicListExample = () => {const { list, remove, getKey, insert, move, replace, reset } = useDynamicList([{ name: "张三", age: 25 },{ name: "李四", age: 30 },{ name: "王五", age: 28 },]);const [inputName, setInputName] = React.useState("");const [inputAge, setInputAge] = React.useState("");const handleAdd = () => {if (inputName && inputAge) {insert(0, { name: inputName, age: parseInt(inputAge) });setInputName("");setInputAge("");}};return (<div><div style={{ marginBottom: 16 }}><Inputplaceholder="姓名"value={inputName}onChange={(e) => setInputName(e.target.value)}style={{ width: 120, marginRight: 8 }}/><Inputplaceholder="年龄"value={inputAge}onChange={(e) => setInputAge(e.target.value)}style={{ width: 80, marginRight: 8 }}/><Button type="primary" onClick={handleAdd}>添加到开头</Button><Button onClick={reset} style={{ marginLeft: 8 }}>重置</Button></div>{list.map((item, index) => (<Cardkey={getKey(index)}size="small"style={{ marginBottom: 8 }}extra={<div><Buttonsize="small"onClick={() => move(index, index - 1)}disabled={index === 0}>上移</Button><Buttonsize="small"onClick={() => move(index, index + 1)}disabled={index === list.length - 1}style={{ marginLeft: 4 }}>下移</Button><Buttonsize="small"dangeronClick={() => remove(index)}style={{ marginLeft: 4 }}>删除</Button></div>}><p><strong>姓名:</strong> {item.name}</p><p><strong>年龄:</strong> {item.age}</p></Card>))}</div>);
};

useVirtualList – 虚拟列表

import React, { useMemo, useRef } from "react";
import { useVirtualList } from "ahooks";export default function Demo() {const containerRef = useRef(null);const wrapperRef = useRef(null);// 生成大量测试数据const originalList = useMemo(() => {return Array.from({ length: 10000 }, (_, index) => ({id: index,title: `列表项 ${index + 1}`,content: `这是第 ${index + 1} 个列表项的内容,包含一些示例文本。`,timestamp: new Date(Date.now() - Math.random() * 10000000000).toLocaleString(),}));}, []);// 使用 useVirtualList hook - 正确版本const [list] = useVirtualList(originalList, {containerTarget: containerRef,wrapperTarget: wrapperRef,itemHeight: 80,overscan: 10,});console.log("originalList length:", originalList.length);console.log("virtual list length:", list.length);console.log("containerRef:", containerRef);console.log("wrapperRef:", wrapperRef);// 计算总高度const totalHeight = originalList.length * 80; // 每个项目80px高度console.log("totalHeight:", totalHeight);console.log("list first item:", list?.[0]);// 如果虚拟列表不工作,先显示普通列表const showNormalList = !list || list.length === 0;return (<div className="p-6 max-w-4xl mx-auto"><h1 className="text-3xl font-bold text-gray-800 mb-6">useVirtualList 虚拟列表示例</h1><div className="mb-4 text-sm text-gray-600">总共 {originalList.length} 个列表项,但只渲染可见区域的项目{showNormalList && (<span className="text-orange-600"> (使用普通列表作为备用)</span>)}</div>{/* 虚拟列表容器 */}<divref={containerRef}className="border border-gray-200 rounded-lg overflow-y-auto bg-white shadow-sm"style={{ height: "600px" }}><div ref={wrapperRef}>{showNormalList? // 备用:普通列表originalList.slice(0, 20).map((item) => (<divkey={item.id}className="border-b border-gray-100 p-4 hover:bg-gray-50 transition-colors"style={{ height: "80px" }}><div className="flex items-center justify-between"><div className="flex-1"><h3 className="font-semibold text-gray-800 mb-1">{item.title}</h3><p className="text-sm text-gray-600 line-clamp-2">{item.content}</p></div><div className="text-xs text-gray-400 ml-4">{item.timestamp}</div></div></div>)): // 虚拟列表list.map((item) => (<divkey={item.index}className="border-b border-gray-100 p-4 hover:bg-gray-50 transition-colors"style={{ height: "80px" }}><div className="flex items-center justify-between"><div className="flex-1"><h3 className="font-semibold text-gray-800 mb-1">{item.data.title}</h3><p className="text-sm text-gray-600 line-clamp-2">{item.data.content}</p></div><div className="text-xs text-gray-400 ml-4">{item.data.timestamp}</div></div></div>))}</div></div></div>);
}

6. useHistoryTravel – 历史记录

import React from "react";
import { useHistoryTravel } from "ahooks";
import { Button, Input, Card } from "antd";const HistoryTravelExample = () => {const { value, setValue, backLength, forwardLength, back, forward, reset } =useHistoryTravel("");const handleChange = (e) => {setValue(e.target.value);};return (<div><Card title="历史记录管理" style={{ marginBottom: 16 }}><div style={{ marginBottom: 16 }}><Inputvalue={value}onChange={handleChange}placeholder="输入内容,每次修改都会记录历史"style={{ marginBottom: 8 }}/><div><Button onClick={reset} style={{ marginRight: 8 }}>重置</Button><span style={{ color: "#666" }}>当前值: {value || "(空)"}</span></div></div><div style={{ marginBottom: 16 }}><Buttondisabled={backLength <= 0}onClick={back}style={{ marginRight: 8 }}>后退 ({backLength})</Button><Buttondisabled={forwardLength <= 0}onClick={forward}style={{ marginRight: 8 }}>前进 ({forwardLength})</Button></div></Card><Card title="历史记录信息"><p><strong>可后退步数:</strong> {backLength}</p><p><strong>可前进步数:</strong> {forwardLength}</p><p><strong>总历史记录数:</strong> {backLength + forwardLength + 1}</p></Card></div>);
};

useNetwork – 网络状态

import React from "react";
import { useNetwork } from "ahooks";
import { Card, Tag, Alert } from "antd";const NetworkExample = () => {const network = useNetwork();const getNetworkStatus = () => {if (network.online) {return <Tag color="green">在线</Tag>;}return <Tag color="red">离线</Tag>;};const getNetworkType = () => {if (network.effectiveType) {return <Tag color="blue">{network.effectiveType}</Tag>;}return <Tag color="orange">未知</Tag>;};return (<div><Card title="网络状态监控"><div style={{ marginBottom: 16 }}><strong>连接状态:</strong> {getNetworkStatus()}</div><div style={{ marginBottom: 16 }}><strong>网络类型:</strong> {getNetworkType()}</div>{!network.online && (<Alertmessage="网络连接已断开"description="请检查您的网络连接,某些功能可能无法正常使用。"type="warning"showIconstyle={{ marginBottom: 16 }}/>)}<Card title="详细网络信息" size="small"><p><strong>在线状态:</strong> {network.online ? "是" : "否"}</p><p><strong>网络类型:</strong> {network.effectiveType || "未知"}</p><p><strong>下行速度:</strong>{" "}{network.downlink ? `${network.downlink} Mbps` : "未知"}</p><p><strong>往返时间:</strong>{" "}{network.rtt ? `${network.rtt} ms` : "未知"}</p><p><strong>保存数据模式:</strong> {network.saveData ? "是" : "否"}</p></Card></Card></div>);
};

useSelections – 多选管理

import React, { useMemo } from "react";
import { useSelections } from "ahooks";
import { Checkbox, Button, Card, List } from "antd";const SelectionsExample = () => {const list = useMemo(() => [{ id: 1, name: "苹果", price: 5.5 },{ id: 2, name: "香蕉", price: 3.2 },{ id: 3, name: "橙子", price: 4.8 },{ id: 4, name: "葡萄", price: 8.9 },{ id: 5, name: "草莓", price: 12.5 },{ id: 6, name: "蓝莓", price: 15.8 },],[]);const {selected,allSelected,isSelected,toggle,toggleAll,partiallySelected,} = useSelections(list, {defaultSelected: [list[0], list[2]], // 默认选中第一个和第三个项});const totalPrice = selected.map((item) => item.price || 0).reduce((sum, price) => sum + price, 0);// 调试信息console.log("selected:", selected);console.log("allSelected:", allSelected);console.log("partiallySelected:", partiallySelected);console.log("list:", list);return (<div><divstyle={{marginBottom: 16,padding: "10px",backgroundColor: "#f5f5f5",borderRadius: "4px",}}><strong>当前选中项 ID:</strong>{" "}{selected.map((item) => item.id).join(", ") || "无"}</div><Card title="多选管理示例" style={{ marginBottom: 16 }}><div style={{ marginBottom: 16 }}><Checkboxchecked={allSelected}onClick={toggleAll}indeterminate={partiallySelected}style={{ marginRight: 8 }}>全选</Checkbox><span style={{ color: "#666" }}>已选择 {selected.length} 项,总价: ¥{totalPrice.toFixed(2)}</span></div><ListdataSource={list}renderItem={(item) => (<List.Itemstyle={{display: "flex",justifyContent: "space-between",alignItems: "center",padding: "8px 0",borderBottom: "1px solid #f0f0f0",}}><div style={{ display: "flex", alignItems: "center" }}><Checkboxchecked={isSelected(item)}onClick={() => toggle(item)}style={{ marginRight: 8 }}/><span>{item.name}</span></div><span style={{ color: "#666" }}>¥{item.price}</span></List.Item>)}/></Card></div>);
};

useCountDown – 倒计时

import React, { useState } from "react";
import { useCountDown } from "ahooks";
import { Button, Card, Input, message } from "antd";const SmsCountDownExample = () => {const [phoneNumber, setPhoneNumber] = useState("");const [targetDate, setTargetDate] = useState();const [countdown] = useCountDown({targetDate,onEnd: () => {console.log("倒计时结束!");message.success("倒计时结束,可以重新发送短信");},});const formatTime = (ms) => {const seconds = Math.floor(ms / 1000);return seconds.toString().padStart(2, "0");};const handleSendSms = () => {if (!phoneNumber) {message.error("请输入手机号码");return;}if (phoneNumber.length !== 11) {message.error("请输入正确的11位手机号码");return;}// 模拟发送短信message.success(`验证码已发送到 ${phoneNumber}`);// 开始60秒倒计时setTargetDate(Date.now() + 60000);};const handleReset = () => {setTargetDate(undefined);};return (<div><Card title="短信验证码倒计时" style={{ marginBottom: 16 }}><div style={{ marginBottom: 16 }}><Inputplaceholder="请输入手机号码"value={phoneNumber}onChange={(e) => setPhoneNumber(e.target.value)}style={{ marginBottom: 8 }}maxLength={11}/><div style={{ display: "flex", alignItems: "center", gap: 8 }}><Buttontype="primary"onClick={handleSendSms}disabled={countdown !== 0}style={{ flex: 1 }}>{countdown === 0? "发送验证码": `重新发送(${formatTime(countdown)}s)`}</Button>{countdown !== 0 && (<Button onClick={handleReset} size="small">重置</Button>)}</div></div></Card></div>);
};

useCounter – 计数器

import React from "react";
import { useCounter } from "ahooks";
import { Button, Card, InputNumber, Space } from "antd";const CounterExample = () => {const [current, { inc, dec, set, reset }] = useCounter(1, {min: 1,max: 10,});return (<div><Card title="useCounter 计数器示例" style={{ marginBottom: 16 }}><div style={{ textAlign: "center", marginBottom: 16 }}><divstyle={{ fontSize: "32px", fontWeight: "bold", color: "#1890ff" }}>{current}</div></div><div style={{ textAlign: "center", marginBottom: 16 }}><Space><Buttontype="primary"onClick={() => inc()}style={{ marginRight: 8 }}>inc(1)</Button><Button onClick={() => dec()} style={{ marginRight: 8 }}>dec(1)</Button><Button onClick={() => set(3)} style={{ marginRight: 8 }}>set(3)</Button><Button onClick={reset} style={{ marginRight: 8 }}>reset(0)</Button></Space></div><div style={{ textAlign: "center" }}><Space><InputNumbermin={1}max={10}value={current}onChange={(value) => set(value || 1)}style={{ width: 100 }}/><span style={{ color: "#666" }}>直接输入数值</span></Space></div></Card></div>);
};

useTextSelection – 文本选择

import React from "react";
import { useTextSelection } from "ahooks";
import { Card } from "antd";const TextSelectionExample = () => {const selection = useTextSelection();return (<div><Card title="文本选择监听" style={{ marginBottom: 16 }}><divstyle={{padding: "16px",border: "1px solid #d9d9d9",borderRadius: "6px",backgroundColor: "#fafafa",lineHeight: "1.8",}}><p>这是一段示例文本,您可以在这里选择任意内容。选择文本后,下方会显示选择的相关信息,包括选中的文本内容、选择的位置信息等。这个功能在需要获取用户选择的文本内容时非常有用,比如实现文本高亮、复制选中内容等功能。</p><p>您可以尝试选择单个单词、短语或者整段文本,观察下方信息的变化。选择不同的文本内容,会得到不同的选择结果。</p></div></Card><Card title="选择信息" size="small" style={{ marginBottom: 16 }}>{selection.text ? (<div><p><strong>选中的文本:</strong></p><divstyle={{padding: "8px",backgroundColor: "#f0f0f0",borderRadius: "4px",marginBottom: "8px",wordBreak: "break-all",}}>"{selection.text}"</div>{selection.rects && selection.rects.length > 0 && (<div><p><strong>选择区域:</strong></p><div style={{ fontSize: "12px", color: "#666" }}><p>区域数量: {selection.rects.length}</p>{selection.rects.map((rect, index) => (<p key={index}>区域 {index + 1}: x={rect.x.toFixed(0)}, y={rect.y.toFixed(0)}, 宽={rect.width.toFixed(0)}, 高={rect.height.toFixed(0)}</p>))}</div></div>)}</div>) : (<div style={{ color: "#999", textAlign: "center" }}>请在上方文本中选择内容</div>)}</Card></div>);
};

useWebSocket – WebSocket 连接

import React, { useState } from "react";
import { useWebSocket } from "ahooks";
import { Button, Card, Input, List, Tag, Alert } from "antd";const WebSocketExample = () => {const [url, setUrl] = useState("ws://localhost:8080");const [message, setMessage] = useState("");const { readyState, sendMessage, latestMessage, disconnect, connect } =useWebSocket(url, {onOpen: () => {console.log("WebSocket连接成功");},onMessage: (message) => {console.log("收到消息:", message);},onError: (error) => {console.log("WebSocket错误:", error);},onClose: () => {console.log("WebSocket连接关闭");},manual: true, // 手动连接});const [messageHistory, setMessageHistory] = useState([]);React.useEffect(() => {if (latestMessage) {setMessageHistory((prev) => [...prev,{id: Date.now(),content: latestMessage.data,type: "received",time: new Date().toLocaleTimeString(),},]);}}, [latestMessage]);const handleSend = () => {if (message.trim()) {sendMessage(message);setMessageHistory((prev) => [...prev,{id: Date.now(),content: message,type: "sent",time: new Date().toLocaleTimeString(),},]);setMessage("");}};const getStatusText = () => {switch (readyState) {case 0:return { text: "连接中", color: "processing" };case 1:return { text: "已连接", color: "success" };case 2:return { text: "关闭中", color: "warning" };case 3:return { text: "已关闭", color: "error" };default:return { text: "未知", color: "default" };}};const status = getStatusText();return (<div><Card title="WebSocket 连接管理" style={{ marginBottom: 16 }}><div style={{ marginBottom: 16 }}><Inputvalue={url}onChange={(e) => setUrl(e.target.value)}placeholder="WebSocket URL"style={{ marginBottom: 8 }}/><div><Buttontype="primary"onClick={connect}disabled={readyState === 1}style={{ marginRight: 8 }}>连接</Button><ButtononClick={disconnect}disabled={readyState !== 1}style={{ marginRight: 8 }}>断开</Button><Tag color={status.color}>状态: {status.text}</Tag></div></div>{readyState === 3 && (<Alertmessage="连接已断开"description="请点击连接按钮重新建立WebSocket连接"type="warning"showIconstyle={{ marginBottom: 16 }}/>)}</Card><Card title="消息收发" style={{ marginBottom: 16 }}><div style={{ marginBottom: 16 }}><Input.TextAreavalue={message}onChange={(e) => setMessage(e.target.value)}placeholder="输入要发送的消息"rows={3}style={{ marginBottom: 8 }}onPressEnter={(e) => {if (!e.shiftKey) {e.preventDefault();handleSend();}}}/><Buttontype="primary"onClick={handleSend}disabled={readyState !== 1 || !message.trim()}>发送消息</Button></div><Listsize="small"dataSource={messageHistory}renderItem={(item) => (<List.Itemstyle={{padding: "8px 0",borderBottom: "1px solid #f0f0f0",}}><div style={{ width: "100%" }}><divstyle={{display: "flex",justifyContent: "space-between",marginBottom: "4px",}}><Tag color={item.type === "sent" ? "blue" : "green"}>{item.type === "sent" ? "发送" : "接收"}</Tag><span style={{ fontSize: "12px", color: "#666" }}>{item.time}</span></div><divstyle={{padding: "8px",backgroundColor:item.type === "sent" ? "#e6f7ff" : "#f6ffed",borderRadius: "4px",wordBreak: "break-all",}}>{item.content}</div></div></List.Item>)}/></Card><Card title="连接信息" size="small"><p><strong>连接状态:</strong><Tag color={status.color}>{status.text}</Tag></p><p><strong>连接URL:</strong> {url}</p><p><strong>消息总数:</strong> {messageHistory.length}</p><p><strong>最后消息:</strong> {latestMessage?.data || "无"}</p></Card></div>);
};

useTheme – 主题

import React from "react";
import { useTheme } from "ahooks";
import { Button, Card, Tag } from "antd";const ThemeExample = () => {const { theme, themeMode, setThemeMode } = useTheme({localStorageKey: "themeMode",});return (<div><Card title="useTheme 基础用法" style={{ marginBottom: 16 }}><div style={{ marginBottom: 16 }}><p><strong>theme:</strong> <Tag color="blue">{theme}</Tag></p><p><strong>themeMode:</strong> <Tag color="green">{themeMode}</Tag></p></div><div style={{ marginBottom: 16 }}><Buttontype="primary"onClick={() => setThemeMode("dark")}style={{ marginRight: 8 }}>使用深色主题</Button><ButtononClick={() => setThemeMode("light")}style={{ marginRight: 8 }}>使用浅色主题</Button><ButtononClick={() => setThemeMode("system")}style={{ marginRight: 8 }}>跟随系统</Button></div><divstyle={{padding: "16px",border: "1px solid #d9d9d9",borderRadius: "6px",backgroundColor: theme === "dark" ? "#141414" : "#ffffff",color: theme === "dark" ? "#ffffff" : "#000000",transition: "all 0.3s ease",}}><h3 style={{ marginBottom: 12 }}>主题预览区域</h3><p>这是一个主题预览区域,展示了当前主题的样式效果。 当前主题: {theme},主题模式: {themeMode}</p></div></Card></div>);
};

通过合理使用这些 hooks,可以大大简化 React 应用的开发复杂度,提高代码的可维护性和用户体验。

场景类 hooks 速查表

Hook 名称用途描述
useAntdTableAntd 表格集成专门为 Ant Design Table 组件设计的 hook,简化表格数据获取和分页管理
useFusionTableFusion 表格集成专门为 Fusion Design Table 组件设计的 hook,提供表格数据管理功能
useInfiniteScroll无限滚动实现无限滚动加载,支持触底加载更多数据,自动处理加载状态
usePagination分页管理简化分页数据的获取和管理,自动处理页码和页面大小的状态
useDynamicList动态列表管理动态增减的列表项,支持添加、删除、移动等操作
useVirtualList虚拟列表实现大数据量的虚拟滚动列表,提升性能,减少 DOM 节点数量
useHistoryTravel历史记录管理状态的历史记录,支持前进、后退、跳转到指定历史点
useNetwork网络状态监听网络连接状态变化,包括在线/离线状态和网络类型
useSelections多选管理管理列表的多选状态,支持全选、反选、批量操作等功能
useCountDown倒计时实现倒计时功能,支持自定义格式和回调函数
useCounter计数器管理数字计数器的增删改查操作,支持步长设置
useTextSelection文本选择监听用户文本选择事件,获取选中的文本内容和位置信息
useWebSocketWebSocket 连接管理 WebSocket 连接,处理连接、断开、消息收发等操作
useTheme主题管理管理应用主题状态,支持主题切换和持久化存储

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/88750.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/88750.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大模型之Langchain篇(二)——RAG

写在前面 跟着楼兰老师学习【LangChain教程】2025吃透LangChain框架快速上手与深度实战&#xff0c;全程干货无废话&#xff0c;三天学完&#xff0c;让你少走百分之99弯路&#xff01;_哔哩哔哩_bilibili 计算相似度 一般用的余弦相似度&#xff0c;这里只是演示计算。 fr…

深入理解图像二值化:从静态图像到视频流实时处理

一、引言&#xff1a;图像分析&#xff0c;从“黑与白”开始在计算机视觉任务中&#xff0c;**图像二值化&#xff08;Image Binarization&#xff09;**是最基础也是最关键的图像预处理技术之一。它通过将灰度图像中每个像素转换为两个离散值&#xff08;通常是0和255&#xf…

云蝠智能 VoiceAgent重构企业呼入场景服务范式

在数字化转型浪潮中&#xff0c;企业呼入场景面临客户服务需求激增与人力成本攀升的双重挑战。传统呼叫中心日均处理仅 300-500 通电话&#xff0c;人力成本占比超 60%&#xff0c;且服务质量受情绪波动影响显著。云蝠智能推出的 VoiceAgent 语音智能体&#xff0c;通过全栈自研…

java进阶(一)+学习笔记

1.JAVA设计模式1.1 什么是设计模式设计模式是软件开发过程中前辈们在长期实践中针对重复出现的问题总结出来的最佳解决方案。这些模式不是具体的代码实现&#xff0c;而是经过验证的、可重用的设计思想&#xff0c;能够帮助开发者更高效地解决特定类型的问题。设计模式的重要性…

Pandas-数据清洗与处理

Pandas-数据清洗与处理一、数据清洗的核心目标二、缺失值处理1. 缺失值检测2. 缺失值处理策略&#xff08;1&#xff09;删除法&#xff08;2&#xff09;填充法三、异常值识别与处理1. 异常值检测方法&#xff08;1&#xff09;统计法&#xff08;2&#xff09;业务规则法2. 异…

在 MacOS 上安装和配置 Kafka

消息代理是一种软件&#xff0c;充当在不同应用程序之间发送消息的中介。它的功能类似于服务器&#xff0c;从一个应用程序&#xff08;称为生产者&#xff09;接收消息&#xff0c;并将其路由到一个或多个其他应用程序&#xff08;称为消费者&#xff09;。消息代理的主要目的…

基于Leaflet调用天地图在线API的多层级地名检索实战

目录 前言 一、天地图在线检索 1、在线检索功能 2、再谈后后接口 二、Leaflet多层级实现实例 1、层级调用实现原理 2、Leaflet中多层级调用 3、成果展示 三、总结 前言 “地图是世界的索引&#xff0c;而地名则是索引中的索引。”当互联网地图进入 Web 2.0 时代&#x…

基于Prompt结构的语校解析:3H日本语学校信息建模实录(4/500)

基于Prompt结构的语校解析&#xff1a;3H日本语学校信息建模实录&#xff08;4/500&#xff09; 系列延续&#xff1a;500所日本语言学校结构数据工程 关键词&#xff1a;招生结构、JLPTEJU、国籍比例、认定校、Prompt训练集 一、我们在构建什么样的语言学校语料&#xff1f; …

Leaflet面试题及答案(61-80)

查看本专栏目录 文章目录 🟢 面试问题及答案(61-80)61. 如何在地图上显示一个动态更新的图层?62. 如何实现地图上的热力图(Heatmap)?63. 如何自定义地图控件的位置?64. 如何处理地图加载失败的情况?65. 如何实现地图的离线功能?66. 如何将地图导出为图片?67. 如何实…

MIG_IP核的时钟系统

MIG_IP核的时钟系统时钟的种类和配置时钟的种类和配置 整体框图 DDR_PHY_CLK&#xff1a;DDR3的工作频率&#xff0c;用来得到想要的线速率。假设此时钟为800M&#xff0c;那么DDR双沿采样&#xff0c;线速率为1600Mbit&#xff1b; UI_CLK&#xff1a;DDR_PHY_CLK的四分之一…

若依框架集成阿里云OSS实现文件上传优化

背景介绍 在若依框架目前的实现中&#xff0c;是把图片存储到了服务器本地的目录&#xff0c;通过服务进行访问&#xff0c;这样做存储的是比较省事&#xff0c;但是缺点也有很多&#xff1a; 硬件与网络要求&#xff1a;服务器通常需要高性能的硬件和稳定的网络环境&#xff0…

Mac如何连接惠普M126a打印机(教程篇)

这里写自定义目录标题Mac如何连接惠普M126a打印机&#xff08;教程篇&#xff09;教程配置如下&#xff1a;Mac如何连接惠普M126a打印机&#xff08;教程篇&#xff09; 惠普M126a连接Mac&#xff08;教程篇&#xff09; 教程配置如下&#xff1a; 首先&#xff0c;先获取与HP打…

感恩日记:记录生活中的美好时刻

感恩日记的landing page登录注册填写感恩事项私信可以体验一下

一扇门铃,万向感应——用 eventfd 实现零延迟通信

&#x1f50d; 本篇概要 eventfd 是 Linux 提供的一种轻量级事件通知机制。你可以把它想象成一个“计数器盒子”。它里面维护的是一个64位的计数器。写入&#xff1a;往盒子里放一些数字&#xff08;比如 1、5、10&#xff09;&#xff0c;表示有几件事发生了。读取&#xff1a…

基于Node.js的线上教学系统的设计与实现(源码+论文+调试+安装+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。系统背景近年来&#xff0c;全球数字化浪潮的推进与教育公平化需求的增长&#xff0c;促使线上教学迎…

互斥锁详解(操作系统os)

1. 互斥锁 (Mutex) - 档案室的“智能锁”首先&#xff0c;我们给之前讨论的那些“锁”一个正式的名字&#xff1a;互斥锁 (Mutex)。概念&#xff1a;你可以把它简单理解成档案室门上的一把“智能锁”。它只有两种状态&#xff1a;locked (已上锁) 或 unlocked (未上锁)。操作&a…

自动润滑系统:从 “盲目养护“ 到智能精注的工业运维革命

​在工业运维的漫长历史中&#xff0c;传统润滑模式如同"定时喂饭"——无论设备实际需求&#xff0c;仅凭经验或固定周期执行润滑作业。这种模式埋下两大隐患&#xff1a;过度润滑&#xff1a;某汽车生产线曾因季度性强制润滑&#xff0c;每年浪费1.2吨润滑脂&#x…

【Java八股文总结 — 包学会】(二)计算机网络

1.一条url输入到浏览器最后显示页面的过程 URL解析与处理 浏览器解析URL&#xff08;如https://www.example.com/page&#xff09; 分离协议&#xff08;https&#xff09;、域名&#xff08;www.example.com&#xff09;和资源路径&#xff08;/page&#xff09; 检查HSTS预加…

力扣61.旋转链表

给你一个链表的头节点 head &#xff0c;旋转链表&#xff0c;将链表每个节点向右移动 k 个位置。示例 1&#xff1a;输入&#xff1a;head [1,2,3,4,5], k 2 输出&#xff1a;[4,5,1,2,3]示例 2&#xff1a;输入&#xff1a;head [0,1,2], k 4 输出&#xff1a;[2,0,1]提示…

深度剖析:std::vector 内存机制与 push_back 扩容策略

深度剖析&#xff1a;std::vector 内存机制与 push_back 扩容策略 1. std::vector 核心内部结构 #mermaid-svg-8HOj3MqsD6UVgEeA {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-8HOj3MqsD6UVgEeA .error-icon{fill:…