@@ -5,6 +5,21 @@ import { offsetPaginator, responseToData } from './utils';
5
5
6
6
const { CancelToken } = axios ;
7
7
8
+ /**
9
+ * Paginator function used to alter the axios config object, in order to fetch the next page.
10
+ * @typedef {function } paginatorFunc
11
+ * @param config {Object} - Axios config object
12
+ * @param paginationState {Object} - Object kept internally to keep track of pagination
13
+ * @return output {Object[]} - Return tuple \[updatedConfig: Object, updatedPaginationState: Object\]
14
+ */
15
+
16
+ /**
17
+ * Function used to extract items from the API response.
18
+ * @typedef {function } responseToItemsFunc
19
+ * @param response {Object} - Axios response object
20
+ * @return output {Object} - Return tuple \[items: Object[], hasMore: boolean\]
21
+ */
22
+
8
23
/**
9
24
* The object returned by the useInfAPI hook.
10
25
* @typedef {Object } useInfAPIOutput
@@ -13,7 +28,7 @@ const { CancelToken } = axios;
13
28
* @property {boolean } isLoading - Indicates if their is a pending API call for the **first** page of items.
14
29
* @property {boolean } isPaging - Indicates if their is a pending API call for the **any** page of items.
15
30
* @property {setItemsFunc } setItems - Set the items being kept in state
16
- * @property {function } fetchMore - Function called from the component in order to fetch the next page
31
+ * @property {responseToItemsFunc } fetchPage - Function called from the component in order to fetch the next page
17
32
*/
18
33
19
34
/**
@@ -27,10 +42,14 @@ const { CancelToken } = axios;
27
42
*
28
43
* Allows you to pass an [axios config object](https://github.com/axios/axios#request-config), for complete control of the request being sent.
29
44
*
45
+ * By default it will paginate using a query param `offset`, and assumes that the API returns an array of items.
46
+ *
47
+ * If this is not appropriate for your API, then you will need to provide your own `paginator` and `responseToItems` functions.
48
+ *
30
49
* @param {string } url - URL that the API call is made to.
31
50
* @param {Object } config={} - Axios config object passed to the axios.request method.
32
- * @param {function } paginator= - Function used to update the config object in order to paginate
33
- * @param {function } responseToItems= - Function used to extract an array of items from response object.
51
+ * @param {paginatorFunc } paginator=offsetPaginator - Function used to update the config object in order to paginate
52
+ * @param {function } responseToItems=responseToData - Function used to extract an array of items from response object.
34
53
* @returns {useInfAPIOutput } output
35
54
*/
36
55
function useInfAPI (
@@ -45,33 +64,42 @@ function useInfAPI(
45
64
error : undefined ,
46
65
isLoading : true ,
47
66
isPaging : true ,
48
- hasMore : false
67
+ hasMore : false ,
68
+ source : CancelToken . source ( )
49
69
} ) ;
50
70
51
71
const configHash = hash ( config ) ;
52
72
53
73
const { items, paginationState } = state ;
54
74
55
- function callAPI ( cancelToken , isLoading ) {
75
+ function callAPI ( isLoading ) {
56
76
const activePaginationState = isLoading ? { } : paginationState ; // Reset pagination when config object changes.
57
77
const [ updatedConfig , updatedPaginationState ] = paginator ( config , activePaginationState ) ;
58
78
59
- setState ( { ...state , isLoading, isPaging : true , paginationState : updatedPaginationState } ) ;
79
+ setState ( {
80
+ ...state ,
81
+ isLoading,
82
+ isPaging : true ,
83
+ paginationState : updatedPaginationState
84
+ } ) ;
60
85
axios ( url , {
61
86
...updatedConfig ,
62
- cancelToken
87
+ cancelToken : state . source . token
63
88
} )
64
89
. then ( response => {
65
90
const [ pageItems , hasMore ] = responseToItems ( response ) ;
66
- if ( pageItems instanceof [ ] ) {
91
+ if ( typeof pageItems === typeof [ ] ) {
67
92
setState ( {
68
93
...state ,
69
94
items : items . concat ( pageItems ) ,
70
95
error : undefined ,
71
96
isLoading : false ,
72
97
isPaging : false ,
73
- hasMore
98
+ hasMore,
99
+ paginationState : updatedPaginationState
74
100
} ) ;
101
+ } else {
102
+ console . log ( "Warning: responseToItems didn't return an array." ) ;
75
103
}
76
104
} )
77
105
. catch ( error => {
@@ -83,25 +111,23 @@ function useInfAPI(
83
111
} ) ;
84
112
}
85
113
86
- let source ;
87
114
useEffect ( ( ) => {
88
- source = CancelToken . source ( ) ;
89
- callAPI ( source . token , true ) ;
115
+ setState ( { ... state , source : CancelToken . source ( ) } ) ;
116
+ callAPI ( true ) ;
90
117
return ( ) => {
91
- source . cancel ( 'useEffect cleanup.' ) ;
118
+ state . source . cancel ( 'useEffect cleanup.' ) ;
92
119
} ;
93
120
} , [ url , configHash ] ) ;
94
121
95
122
const { error, isPaging, isLoading, hasMore } = state ;
96
-
97
123
return {
98
124
items,
99
125
error,
100
126
isPaging,
101
127
isLoading,
102
128
hasMore,
103
129
setItems : newItems => setState ( { ...state , items : newItems } ) ,
104
- fetchPage : ( ) => callAPI ( source . token , false )
130
+ fetchPage : ( ) => callAPI ( false )
105
131
} ;
106
132
}
107
133
0 commit comments