@sevenvip666/react-art
v2.0.2
Published
a request template
Readme
art
一个面向 React 的请求状态库,支持 query、mutation、分页、缓存、共享 store,以及对象式细粒度更新。
安装
pnpm add @sevenvip666/react-artnpm install @sevenvip666/react-art核心特性
useQuery / useMutation / usePaginationmakeQuery / makeMutation / makePagination- callable store:
store()和store(selector) - 对象式细粒度更新:没读到的字段更新时不触发当前组件 re-render
- selector 订阅能力
- 请求缓存、重新验证、轮询、重试
fetch/axios双请求模式sharedKey共享 store
快速开始
useQuery
import { useQuery } from '@sevenvip666/react-art'
function UserView() {
const { data, isLoading, query, refresh } = useQuery<
{ id: number; name: string },
{ id: number }
>('/api/user/detail', {
defaultBody: { id: 1 },
loading: true
})
return (
<div>
{isLoading ? 'loading...' : data?.name}
<button onClick={() => query({ id: 2 })}>load</button>
<button onClick={() => refresh()}>refresh</button>
</div>
)
}makeQuery + store()
import { makeQuery } from '@sevenvip666/react-art'
const userStore = makeQuery<{ name: string }, { id: number }>('/api/user/detail')
function UserView() {
const { data, isLoading } = userStore()
return <div>{isLoading ? 'loading...' : data?.name}</div>
}makeQuery + store(selector)
function UserName() {
const name = userStore((state) => state.data?.name)
return <div>{name}</div>
}请求定义
RequestType<TBody>
请求可以是以下三种形式:
string:请求地址(body: TBody) => string:根据 body 生成地址(body: TBody) => Promise<any>:完全自定义请求
示例:
'/api/user/detail'
(body) => `/api/user/${body.id}`
async (body) => customClient.get('/api/user', { params: body })Hook API
useQuery<TData, TBody>(request, config?, deps?)
用于普通查询。
参数:
request: RequestType<TBody>:请求地址或请求函数config?: HooksQueryConfig<TData, TBody>:查询配置deps?: DependencyList:重新创建 store 的依赖
返回:
QueryStoreType<TData, TBody>
常用返回字段:
data?: TDataoriginData?: TDatabody?: Partial<TBody>status: 'idle' | 'loading' | 'success' | 'error'isLoadingisSuccessisErrorerrorlastRequestTime
常用返回方法:
query(body?, runConfig?)querySync(body?, runConfig?)refresh(config?)refreshSync(config?)setBody(body, replace?)setData(data, replace?)setStatus(status, error?)setCache(data)cancel(message?)clear()
useMutation<TBody, TData>(request, config?, deps?)
用于提交类请求。
参数:
request: RequestType<TBody>config?: HooksMutationConfig<TBody, TData>deps?: DependencyList
返回:
MutationStoreType<TBody, TData>
额外方法:
mutate(body?, runConfig?)mutateSync(body?, runConfig?)
usePagination<TData extends Array<unknown>, TBody>(request, config?, deps?)
用于分页查询或无限加载。
参数:
request: RequestType<TBody>config?: HooksPageConfig<TData, TBody>deps?: DependencyList
返回:
QueryPageStoreType<TData, TBody>
额外字段:
currentpageSizepageTokenstotalhasNextPageisLoadingNextPageisErrorNextPage
额外方法:
query(body?, runConfig?)queryByPage(pageConfig?, runConfig?)queryNextPage(pageConfig?, runConfig?)
useSharedQuery(sharedKey, request, config?, deps?)
与 useQuery 一致,但会通过 sharedKey 复用同一个 store。
useSharedPagination(sharedKey, request, config?, deps?)
与 usePagination 一致,但会通过 sharedKey 复用同一个 store。
makeStore API
makeQuery<TData, TBody>(request, config?)
makeMutation<TBody, TData>(request, config?)
makePagination<TData, TBody>(request, config?)
返回可复用 store,适合:
- 组件外创建
- 多组件共享
- 命令式调用
store 可直接调用:
const store = makeQuery<{ name: string }, { id: number }>('/api/user/detail')
await store.query({ id: 1 })
store.setBody({ id: 2 })
store.setData({ name: 'new name' })
store.clear()在 React 组件中消费时使用:
store()store(selector)
Callable Store
每个 makeQuery / makeMutation / makePagination 创建出来的 store 本身就是 React 消费入口。
store()
返回对象式视图,支持细粒度更新:
const { data, isLoading } = store()store(selector, equalityFn?)
返回选中的值:
const data = store((state) => state.data)
const loading = store((state) => state.isLoading)Selector API
如果你希望显式使用 selector,也可以使用这些 hook:
useArtSelector(store, selector, equalityFn?)useQuerySelector(store, selector, equalityFn?)usePaginationSelector(store, selector, equalityFn?)useMutationSelector(store, selector, equalityFn?)useStoreSelector(store, selector, equalityFn?)
Shared Store API
useSharedQueryStore(key, storeOrFactory, options?)
把已有 store 放进共享池,在多个组件间复用。
参数:
key: stringstoreOrFactory: store | (() => store)options?: { manual?: boolean }
getSharedQueryStore(key)
读取共享 store。
setSharedQueryStore(key, store)
手动写入共享 store。
clearSharedQueryStore(key)
清理指定共享 store,并调用 cancel()。
clearAllSharedQueryStore()
清理全部共享 store,并调用各自的 cancel()。
自动管理 Hook
useAutoQuery(store, body?, deps?)
组件挂载后自动执行 store.query(body)。
useAutoMutate(store, body?, deps?)
组件挂载后自动执行 store.mutate(body)。
useManagedStore(store)
把 store 注册给 Art 管理。用于配合 locale 切换后的自动刷新。
Art 全局配置
Art.setup(config?)
设置全局配置。
import { Art } from '@sevenvip666/react-art'
import axios from 'axios'
Art.setup({
baseURL: 'https://api.example.com',
axios: { axios },
showErrorMessage: (res) => console.error(res.message)
})ArtConfigOptions
基础配置
baseURL?: string:全局请求前缀debug?: booleanlocalCache?: boolean:是否使用本地缓存cacheKeyPrefix?: string:缓存 key 前缀
fetch 模式
fetch?: { fetch?: typeof fetch; requestInit?: (url, method, body) => RequestInit; errorStatus?: number[] }
axios 模式
axios?: { axios: AxiosStatic; instance?: AxiosInstance; instanceCallback?: (instance) => void }
全局 UI 回调
showErrorMessage?: (res) => voidshowSuccessMessage?: (res) => voidstartLoading?: () => voidendLoading?: () => void
响应转换
convertRes?: (res, request?) => UseResult | Promise<UseResult>convertError?: (res, defaultResult) => Partial<UseResult>convertPage?: ({ current, pageSize, nextToken }) => anyhandleHttpError?: (error) => voidhandleCustomHttpError?: (error) => UseResult
缓存扩展
setCacheData?: (key, data) => voidclearCacheData?: (key) => voidgetCacheData?: (key) => CachedData | undefined
重试判断
checkRetry?: (res) => boolean
其他全局方法
Art.setBaseUrl(url)Art.setCacheKeyPrefix(prefix)Art.setLocale(locale?)
setLocale 会刷新当前仍被 React 管理、且已经请求过的非 mutation store。
ArtProvider
ArtProvider
import { ArtProvider } from '@sevenvip666/react-art'
<ArtProvider config={{ baseURL: '/api' }} locale="zh-CN">
<App />
</ArtProvider>参数:
config?: ArtConfigOptionslocale?: string
配置项说明
FetchConfig<TData, TBody>
所有 query / mutation / pagination 共用的基础配置。
status?: boolean:是否自动维护statusloading?: boolean:是否触发全局 loadingstartLoading?: () => voidendLoading?: () => voiddefaultBody?: Partial<TBody> | (() => Partial<TBody>)method?: MethodpostBody?: (body) => any:发请求前转换 bodyshowMessage?: booleanshowErrorMessage?: booleanshowSuccessMessage?: booleansuccessMessage?: stringerrorMessage?: stringdisableCompare?: booleanonSuccess?: (data, cache, isSame?) => voidcustomConfig?: object | ((body) => object):透传给 fetch/axiosonError?: (res) => voidonComplete?: (res) => voidconvertRes?: (res, request) => UseResult | Promise<UseResult>postData?: (data) => TDataloadingDelayMs?: numberdebounceMs?: number | (() => number)throttleMs?: number | (() => number)retry?: numbercheckRetry?: (res) => booleanretryInterval?: numbertimeout?: number
BaseQueryConfig<TData, TBody>
query / pagination 专用配置。
autoClear?: booleancacheType?: 'default' | 'memory'cache?: boolean | string | ((body) => string | boolean)cacheKeys?: string[] | ((body) => Array<string | number | undefined>)cacheLoading?: booleancacheStatus?: booleancacheTime?: numberrevalidate?: numberinitialData?: TData | (() => TData)setInitialData?: TData | (() => TData)placeholderData?: TData | (() => TData)initializeCache?: boolean
FetchRunConfig
运行时配置。
refresh?: booleanreplaceBody?: booleanstatus?: booleanloading?: booleanwhenNoData?: boolean
FetchPageRunConfig
分页运行时配置。
- 继承
FetchRunConfig pageSize?: numberinfinite?: boolean
HooksBaseConfig
hook 层额外配置。
sharedKey?: stringmanual?: booleanpollingIntervalMs?: numberrefreshOnWindowFocus?: booleanrefreshOnWindowFocusMode?: 'run' | 'refresh'refreshOnWindowFocusTimespanMs?: number
StorePageConfig
分页配置。
defaultNextToken?: stringdefaultHasNextPage?: booleantotal?: numbercurrent?: numberpageSize?: numberinfinite?: booleangetNextToken?: (res) => stringhasNextPage?: (res) => boolean
请求返回值
UseResult<TData>
success: booleandata?: TDatamessage?: stringcode?: stringstatus?: numbertotal?: numberisCancel?: booleanother?: anyisSame?: boolean
错误处理工具
handleFetchErrorhandleAxiosError
推荐使用方式
推荐
- 组件内直接请求:
useQuery / useMutation / usePagination - 组件外创建 store:
makeQuery / makeMutation / makePagination + store()
可选增强
store(selector)或useQuerySelector(...)
这条路径更显式,也更适合作为复杂场景或 React Compiler 兼容增强方案。
License
MIT
