@basestone/hooks
v1.5.0
Published
一套用于 React + Ant Design 应用的生产级 Hooks 库,提供表格管理、模态框管理、表单提交、数据请求等常用功能。
Downloads
1,142
Readme
@basestone/hooks
一套用于 React + Ant Design 应用的生产级 Hooks 库,提供表格管理、模态框管理、表单提交、数据请求等常用功能。
✨ 特性
- 🎯 开箱即用 - 提供常用业务场景的完整解决方案
- 💪 TypeScript - 完整的类型定义和类型推导
- 🎨 Ant Design - 深度集成 Ant Design 组件
- ⚡️ 性能优化 - 内置性能优化和记忆化
- 🔧 灵活配置 - 支持全局配置和局部定制
📦 安装
pnpm add @basestone/hooks
# or
npm install @basestone/hooks
# or
yarn add @basestone/hooks📚 Hooks 列表
- useTableList - 表格管理(分页、排序、加载等)
- useCreateModal - 模态框/抽屉管理
- useSelectOptions - 下拉选项管理
- useRequestQuery - 通用数据请求
- useFormSubmit - 表单提交处理
- useMemoizedFn - 函数记忆化
🔧 Claude Code Skill
本库提供了 Claude Code Skill,可以在使用 Claude Code 开发时快速获取帮助和代码示例。
查看 Skill 文档 了解如何在你的项目中使用。
📖 使用文档
useTableList - 表格管理
提供完整的表格管理功能,包括分页、排序、加载状态、行选择等。
import { useTableList } from '@basestone/hooks'
import { Table } from 'antd'
function UserList() {
const { tableProps, search, refresh, reset, queryParams, selectedRowKeys } = useTableList({
queryFn: async (params) => {
// API 返回格式: { status: 'success', data: { list: [], totalCount: 0 } }
return await getUserList(params)
},
params: {
orderField: 'createDate',
orderType: 'DESC',
status: 'active'
},
// 可选:缓存查询条件。默认关闭;key 用于同一列表再次挂载时恢复条件
queryCache: {
enabled: true,
key: 'user-list'
},
rowSelection: true // 启用行选择
})
return (
<div>
<button onClick={() => search({ keyword: 'test' })}>搜索</button>
<button onClick={() => refresh()}>刷新</button>
<Table
rowKey="id"
scroll={{ x: 'max-content' }}
columns={columns}
{...tableProps}
/>
</div>
)
}API:
tableProps- Ant Design Table 所需的所有属性search(params)- 搜索并重置到第一页refresh(params)- 刷新当前页reset(params)- 重置查询参数queryParams- 当前查询参数selectedRowKeys- 选中的行 keys
queryCache 默认不启用。启用后,queryParams 会按 key 缓存在 Zustand store 中,
相同 key 的列表再次挂载时会自动恢复上一次查询条件:
useTableList({
queryFn: getUserList,
queryCache: { enabled: true, key: 'user-list' }
})需要时可以通过相同的 key 清除指定缓存;不传 key 时清除全部表格查询参数:
import { clearTableQueryCache, setTableQueryCache } from '@basestone/hooks'
// 与该 key 已有的查询参数合并
setTableQueryCache('user-list', { status: 'active' })
clearTableQueryCache('user-list')
clearTableQueryCache()useCreateModal - 模态框管理
使用 zustand 管理多个模态框的状态,支持 Modal 和 Drawer。
import { useCreateModal } from '@basestone/hooks'
import { Modal, Drawer } from 'antd'
function UserManagement() {
const { editModal, viewModal, open, close, toggle } = useCreateModal({
edit: {
width: 600,
title: (data) => data?.id ? '编辑用户' : '创建用户',
centered: true,
maskClosable: false
},
view: {
width: 800,
title: '用户详情',
placement: 'right' // Drawer 配置
}
})
return (
<div>
<button onClick={() => open('edit', { id: 1, name: 'John' })}>
编辑用户
</button>
{/* 作为 Modal 使用 */}
<Modal {...editModal.modalProps}>
<div>用户数据: {JSON.stringify(editModal.data)}</div>
</Modal>
{/* 作为 Drawer 使用 */}
<Drawer {...viewModal.drawerProps}>
<div>用户详情: {JSON.stringify(viewModal.data)}</div>
</Drawer>
</div>
)
}API:
{name}Modal.modalProps- Modal 组件属性{name}Modal.drawerProps- Drawer 组件属性{name}Modal.visible- 可见状态{name}Modal.data- 传入的数据open(type, data)- 打开指定模态框close(type)- 关闭指定模态框toggle(type, data)- 切换指定模态框
useSelectOptions - 下拉选项管理
自动获取和管理下拉选项,并创建 value-label 映射。
import { useSelectOptions } from '@basestone/hooks'
import { Select } from 'antd'
function UserFilter() {
const { departmentOptions, departmentMap, loading, refresh } = useSelectOptions({
queryFn: async (params) => {
// API 返回格式: { status: 'success', data: [] }
return await getDepartmentList(params)
},
params: { active: true },
dataKey: 'department', // 会创建 departmentOptions 和 departmentMap
fieldNames: {
label: 'departmentName',
value: 'departmentId'
},
transform: (data) => data.filter(item => item.visible) // 可选的数据转换
})
return (
<Select
options={departmentOptions}
loading={loading}
onChange={(value) => {
console.log('选中值:', value)
console.log('对应标签:', departmentMap.get(value))
}}
/>
)
}API:
{dataKey}Options- 格式化后的选项数组{ label, value, data }{dataKey}Map- value 到 label 的映射 Maploading- 加载状态refresh()- 刷新选项
useRequestQuery - 数据请求
通用的数据请求 Hook,支持 Object 和 Array 类型数据。
import { useRequestQuery } from '@basestone/hooks'
function UserProfile({ userId }) {
// 请求单个对象
const { userInfo, setUserInfo, loading, refresh } = useRequestQuery({
queryFn: async (params) => {
// API 返回格式: { status: 'success', data: {...} }
return await getUserInfo(params)
},
params: { userId },
dataKey: 'userInfo',
dataType: 'Object',
initialValue: { name: '', email: '' },
transform: (data) => ({
...data,
fullName: `${data.firstName} ${data.lastName}`
}),
success: (data) => {
console.log('数据加载成功:', data)
}
})
// 请求数组数据
const { notificationList, setNotificationList } = useRequestQuery({
queryFn: getNotificationList,
params: { userId },
dataKey: 'notificationList',
dataType: 'Array',
initialValue: []
})
// 手动更新数据
const handleUpdateName = () => {
setUserInfo(prev => ({ ...prev, name: '新名字' }))
}
const markAsRead = (id) => {
setNotificationList(prev =>
prev.map(item => item.id === id ? { ...item, read: true } : item)
)
}
return (
<div>
{loading ? '加载中...' : (
<div>
<h1>{userInfo?.fullName}</h1>
<p>{userInfo?.email}</p>
<button onClick={handleUpdateName}>修改名字</button>
</div>
)}
</div>
)
}API:
{dataKey}- 请求到的数据set{DataKey}- 手动更新数据的函数,支持直接设置或函数式更新loading- 加载状态refresh(params)- 刷新数据
useFormSubmit - 表单提交
处理表单提交,自动管理加载状态和消息提示。
import { useFormSubmit } from '@basestone/hooks'
import { Form, Input, Button, App } from 'antd'
function UserForm({ onSuccess }) {
const [form] = Form.useForm()
const { loading, submit } = useFormSubmit(
async (values) => {
// API 返回格式: { status: 'success', info: '操作成功' }
return await createUser(values)
},
(result) => {
form.resetFields()
onSuccess?.(result)
}
)
return (
<App> {/* 必需:message API 依赖 */}
<Form form={form} onFinish={submit}>
<Form.Item name="name" label="姓名" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Button type="primary" htmlType="submit" loading={loading}>
提交
</Button>
</Form>
</App>
)
}API:
loading- 提交中状态submit(values)- 提交函数
useMemoizedFn - 函数记忆化
创建一个稳定引用的函数,但始终调用最新的实现。
import { useMemoizedFn } from '@basestone/hooks'
import { useEffect } from 'react'
function Component() {
const [count, setCount] = useState(0)
// 函数引用永不改变,但总是调用最新的实现
const handleClick = useMemoizedFn(() => {
console.log('当前 count:', count) // 总是打印最新的 count
setCount(count + 1)
})
useEffect(() => {
// handleClick 不会导致 effect 重新运行
}, [handleClick])
return <button onClick={handleClick}>点击 {count}</button>
}🎯 完整示例
import {
useTableList,
useCreateModal,
useSelectOptions,
useFormSubmit
} from '@basestone/hooks'
import { Table, Modal, Form, Input, Select, Button, Space } from 'antd'
function UserManagement() {
const [form] = Form.useForm()
// 表格管理
const { tableProps, refresh } = useTableList({
queryFn: getUserList,
params: { status: 'active' },
rowSelection: true
})
// 模态框管理
const { editModal, open, close } = useCreateModal({
edit: {
width: 600,
title: (data) => data?.id ? '编辑' : '创建'
}
})
// 下拉选项
const { roleOptions } = useSelectOptions({
queryFn: getRoleList,
dataKey: 'role',
fieldNames: { label: 'roleName', value: 'roleId' }
})
// 表单提交
const { loading, submit } = useFormSubmit(
async (values) => {
const api = editModal.data?.id ? updateUser : createUser
return api({ ...values, id: editModal.data?.id })
},
() => {
close('edit')
refresh()
}
)
const columns = [
{ title: '姓名', dataIndex: 'name' },
{ title: '邮箱', dataIndex: 'email' },
{
title: '操作',
render: (_, record) => (
<Space>
<Button onClick={() => open('edit', record)}>编辑</Button>
</Space>
)
}
]
return (
<div>
<Button onClick={() => open('edit')}>创建用户</Button>
<Table rowKey="id" columns={columns} {...tableProps} />
<Modal {...editModal.modalProps}>
<Form form={form} onFinish={submit} initialValues={editModal.data}>
<Form.Item name="name" label="姓名" rules={[{ required: true }]}>
<Input />
</Form.Item>
<Form.Item name="roleId" label="角色">
<Select options={roleOptions} />
</Form.Item>
<Button type="primary" htmlType="submit" loading={loading}>
提交
</Button>
</Form>
</Modal>
</div>
)
}🔌 API 响应格式
所有请求函数应返回以下格式:
// 成功响应
{
status: 'success',
data: any, // 实际数据
info?: string // 可选的消息
}
// useTableList 专用格式
{
status: 'success',
data: {
list: any[], // 数据列表
totalCount: number // 总数
}
}🎨 全局配置
表格全局配置
import { configureTableOption } from '@basestone/hooks'
configureTableOption({
sortField: ['orderType', 'orderField'], // 排序字段名
sortOrder: ['ASC', 'DESC'], // 排序顺序值
pageSize: 20 // 默认每页条数
})💡 最佳实践
- 错误处理: 所有 hooks 内部处理错误,但应确保 API 返回正确的响应格式
- 加载状态: 利用提供的 loading 状态提升用户体验
- 函数记忆化: 对于传递给子组件的回调,使用
useMemoizedFn - 模态框状态: 模态框状态使用 zustand 全局管理,跨渲染保持
- 类型安全: 使用 TypeScript 泛型获得更好的类型推导
📄 依赖
react^19.0.0antd^6.0.0zustand^5.0.0
📝 License
MIT
👨💻 Author
leafront ([email protected])
