Skip to content
This repository was archived by the owner on Aug 4, 2022. It is now read-only.

Commit 02a4218

Browse files
committed
修改 useList 和 useAxios 代码
1 parent 693af05 commit 02a4218

File tree

14 files changed

+284
-210
lines changed

14 files changed

+284
-210
lines changed

src/hooks/useAxios/api.ts

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { useState } from 'react'
2+
3+
import axios, { CancelTokenSource } from 'axios'
4+
5+
import type { UseAxiosService, UseAxiosOptions, UseAxiosState, UseAxiosInstance } from './types'
6+
7+
const CancelToken = axios.CancelToken
8+
9+
const never: Promise<never> = new Promise(() => void 0)
10+
11+
/**
12+
* 使用 axios 封装的 hooks 函数
13+
*
14+
* @todo 支持自定义 axios 实例
15+
* @todo service 支持传递 AxiosRequestConfig
16+
*
17+
* @param service 后台服务
18+
* @param options 可选配置
19+
*/
20+
export function useAxios<T extends object = any, U = any, S extends UseAxiosService<T, U> = any>(
21+
service: S,
22+
options: UseAxiosOptions = {},
23+
): UseAxiosInstance<T, U> {
24+
let cancelSource: CancelTokenSource | null = null
25+
26+
const unique = options.unique !== true
27+
const silent = options.silent !== false
28+
29+
const [state, setState] = useState<UseAxiosState<T>>({
30+
loading: false,
31+
data: null,
32+
error: null,
33+
})
34+
35+
const onSuccess = (data: T) => {
36+
setState({ data, loading: false, error: null })
37+
return data
38+
}
39+
40+
const onError = (error: Error): Promise<never> => {
41+
setState({ data: null, loading: false, error })
42+
return silent ? never : Promise.reject(error)
43+
}
44+
45+
const run = (args: U): Promise<T> => {
46+
if (unique) cancel()
47+
48+
const source = CancelToken.source()
49+
cancelSource = source
50+
51+
setState({ data: null, loading: true, error: null })
52+
return service(args, { cancelToken: source.token }).then(onSuccess, onError)
53+
}
54+
55+
const cancel = (message?: string) => {
56+
if (cancelSource) {
57+
cancelSource.cancel(message)
58+
cancelSource = null
59+
}
60+
}
61+
62+
/** 数据转换 */
63+
function toJSON(): UseAxiosState<T> {
64+
return state
65+
}
66+
67+
return {
68+
...state,
69+
run,
70+
cancel,
71+
toJSON,
72+
}
73+
}

src/hooks/useAxios/index.ts

+2-59
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,2 @@
1-
import { useState } from 'react'
2-
3-
import axios, { CancelTokenSource } from 'axios'
4-
5-
import type { UseAxiosService, UseAxiosOptions, UseAxiosState, UseAxiosInstance } from './types'
6-
7-
const CancelToken = axios.CancelToken
8-
9-
const never: Promise<never> = new Promise(() => {
10-
// pass
11-
})
12-
13-
export function useAxios<T = any, U = any, S extends UseAxiosService<T, U> = any>(
14-
service: S,
15-
options: UseAxiosOptions = {},
16-
): UseAxiosInstance<T, U> {
17-
let cancelSource: CancelTokenSource | null = null
18-
19-
const unique = options.unique !== true
20-
const silent = options.silent !== false
21-
22-
const [state, setState] = useState<UseAxiosState<T>>({
23-
loading: false,
24-
data: null,
25-
error: null,
26-
})
27-
28-
const onSuccess = (data: T) => {
29-
setState({ loading: false, data: data, error: null })
30-
return data
31-
}
32-
const onError = (error: Error): Promise<never> => {
33-
setState({ loading: false, data: null, error })
34-
return silent ? never : Promise.reject(error)
35-
}
36-
37-
const run = (args: U): Promise<T> => {
38-
if (unique) cancel()
39-
40-
const source = CancelToken.source()
41-
cancelSource = source
42-
43-
setState({ loading: true, data: null, error: null })
44-
return service(args, { cancelToken: source.token }).then(onSuccess, onError)
45-
}
46-
47-
const cancel = (message?: string) => {
48-
if (cancelSource) {
49-
cancelSource.cancel(message)
50-
cancelSource = null
51-
}
52-
}
53-
54-
return {
55-
...state,
56-
run,
57-
cancel,
58-
}
59-
}
1+
export * from './api'
2+
export * from './types'

src/hooks/useAxios/types.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,17 @@ export interface UseAxiosOptions {
1111
silent?: boolean
1212
}
1313

14-
export interface UseAxiosInstance<T, P> extends UseAxiosState<T> {
14+
export interface UseAxiosInstance<T, P> {
15+
data: T | null
16+
loading: boolean
17+
error: Error | null
18+
1519
run(args: P): Promise<T>
1620
cancel(message?: string): void
21+
toJSON(): UseAxiosState<T>
1722
}
1823

1924
export type UseAxiosService<T, U> = (args: U, options: AxiosRequestConfig) => Promise<T>
2025

26+
// 不能删除,否则 snowpack 会运行报错
2127
export default {}

src/hooks/useList/hook.ts src/hooks/useList/api.ts

+51-23
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { useState, useMemo } from 'react'
1+
import { useState, useMemo, useEffect } from 'react'
22

3-
import type { UseListOptions, UseListState, LoadOptions, LoadArgs } from './types'
3+
import type { UseListState, UseListOptions, List, UseListInstance, ListFetchOptions, ListFetchArgs } from './types'
44

55
/**
66
* 列表 hook 函数
@@ -23,23 +23,23 @@ import type { UseListOptions, UseListState, LoadOptions, LoadArgs } from './type
2323
*
2424
* @return 返回列表状态与方法
2525
*/
26-
export function useList<T>(options: UseListOptions<T>) {
27-
const dispatchRequest = options.dispatchRequest
26+
export function useList<T>(options: UseListOptions<T>): UseListInstance<T> {
27+
const onFetch = options.onFetch
2828

29+
// 列表变更模式
2930
const mode = options.mode || 'replace'
3031

32+
// 加载状态
33+
const loading = options.loading === true
34+
35+
// 列表状态
3136
const [state, setState] = useState<UseListState<T>>({
3237
items: options.items ?? [],
3338
page: options.page || 1,
3439
pageSize: options.pageSize || 10,
3540
total: options.total || 0,
3641
})
3742

38-
/**
39-
* 加载状态
40-
*/
41-
const loading = useMemo<boolean>(() => options.loading === true, [options.loading])
42-
4343
/**
4444
* 是否第一页
4545
*/
@@ -53,20 +53,30 @@ export function useList<T>(options: UseListOptions<T>) {
5353
state.total,
5454
])
5555

56-
function refresh(options?: LoadOptions) {
57-
return load({}, { ...options, refresh: true })
56+
/**
57+
* 刷新列表
58+
*
59+
* @param options 刷新配置
60+
*/
61+
function refresh(options?: ListFetchOptions) {
62+
return dispatchRequest({}, { ...options, refresh: true })
5863
}
5964

60-
function search(args?: Partial<LoadArgs>) {
65+
/**
66+
* 搜索方法
67+
*
68+
* @param args 搜索参数
69+
*/
70+
function search(args?: Partial<ListFetchArgs>) {
6171
// 默认,搜索就跳转回第一页
62-
return load({ page: 1, ...args }, { force: true })
72+
return dispatchRequest({ page: 1, ...args }, { force: true })
6373
}
6474

6575
function clear() {
6676
setState({ items: [], page: 1, pageSize: 10, total: 0 })
6777
}
6878

69-
async function load(args?: Partial<LoadArgs>, options?: LoadOptions) {
79+
async function dispatchRequest(args?: Partial<ListFetchArgs>, options?: ListFetchOptions) {
7080
args = args || {}
7181
options = options || {}
7282

@@ -77,21 +87,28 @@ export function useList<T>(options: UseListOptions<T>) {
7787
if (options.force !== true) return Promise.resolve()
7888
}
7989

80-
const res = await dispatchRequest({ page, pageSize }, { ...options, state, mode })
90+
const res = await onFetch({ page, pageSize }, { ...options, state, mode })
8191
if (!res) return
8292

8393
let items: T[] = []
8494
if (mode === 'manual' || options.refresh === true) {
85-
items = res.items
95+
items = res.items || []
8696
} else {
87-
items = mode === 'append' ? state.items.concat(res.items) : res.items
97+
items = mode === 'append' ? state.items.concat(res.items || []) : res.items || []
8898
}
8999

90-
setState({ items, page, pageSize, total: res.total })
100+
setState({ items, page: res.page || page, pageSize: res.pageSize || pageSize, total: res.total || 0 })
91101
}
92102

93-
function loadPageData(page: number, options?: LoadOptions) {
94-
return load({ page }, options)
103+
/**
104+
* 加载制定页数据
105+
*
106+
* @param page 指定页
107+
* @param options
108+
* @param options.force 是否强制刷新
109+
*/
110+
function loadPageData(page: number, options?: ListFetchOptions) {
111+
return dispatchRequest({ page }, options)
95112
}
96113

97114
/**
@@ -100,7 +117,7 @@ export function useList<T>(options: UseListOptions<T>) {
100117
* @param options
101118
* @param options.force 是否强制刷新
102119
*/
103-
function loadPreviousPageData(options?: LoadOptions) {
120+
function loadPreviousPageData(options?: ListFetchOptions) {
104121
return isFirst ? Promise.resolve() : loadPageData(state.page - 1, options)
105122
}
106123

@@ -110,15 +127,25 @@ export function useList<T>(options: UseListOptions<T>) {
110127
* @param options 可选项
111128
* @param options.force 是否强制刷新
112129
*/
113-
function loadNextPageData(options?: LoadOptions) {
130+
function loadNextPageData(options?: ListFetchOptions) {
114131
return isEnd ? Promise.resolve() : loadPageData(state.page + 1, options)
115132
}
116133

134+
/** 数据转换 */
135+
function toJSON(): List<T> {
136+
return state
137+
}
138+
139+
useEffect(() => {
140+
// 自动加载
141+
if (options.autoLoad === true) refresh()
142+
}, [])
143+
117144
return {
145+
// state
118146
...state,
119147

120148
// computed
121-
loading,
122149
isFirst,
123150
isEnd,
124151

@@ -132,5 +159,6 @@ export function useList<T>(options: UseListOptions<T>) {
132159

133160
// sync methods
134161
clear,
162+
toJSON,
135163
}
136164
}

src/hooks/useList/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
export * from './hook'
1+
export * from './api'
22
export * from './types'

0 commit comments

Comments
 (0)