MCPcopy Index your code
hub / github.com/adobe/react-spectrum / useAsyncList

Function useAsyncList

packages/react-stately/src/data/useAsyncList.ts:281–382  ·  view source on GitHub ↗
(options: AsyncListOptions<T, C>)

Source from the content-addressed store, hash-verified

279 * to update the data over time. Manages loading and error states, pagination, and sorting.
280 */
281export function useAsyncList<T, C = string>(options: AsyncListOptions<T, C>): AsyncListData<T> {
282 const {
283 load,
284 sort,
285 initialSelectedKeys,
286 initialSortDescriptor,
287 getKey = (item: any) => item.id || item.key,
288 initialFilterText = ''
289 } = options;
290
291 let [data, dispatch] = useReducer<AsyncListState<T, C>, [Action<T, C>]>(reducer, {
292 state: 'idle',
293 error: undefined,
294 items: [],
295 selectedKeys: initialSelectedKeys === 'all' ? 'all' : new Set(initialSelectedKeys),
296 sortDescriptor: initialSortDescriptor,
297 filterText: initialFilterText
298 });
299
300 const dispatchFetch = async (action: Action<T, C>, fn: AsyncListLoadFunction<T, C>) => {
301 let abortController = new AbortController();
302 try {
303 dispatch({...action, abortController});
304 let previousFilterText = action.filterText ?? data.filterText;
305
306 let response = await fn({
307 items: data.items.slice(),
308 selectedKeys: data.selectedKeys,
309 sortDescriptor: action.sortDescriptor ?? data.sortDescriptor,
310 signal: abortController.signal,
311 cursor: action.type === 'loadingMore' ? data.cursor : undefined,
312 filterText: previousFilterText,
313 loadingState: data.state
314 });
315
316 let filterText = response.filterText ?? previousFilterText;
317 dispatch({type: 'success', ...response, abortController});
318
319 // Fetch a new filtered list if filterText is updated via `load` response func rather than list.setFilterText
320 // Only do this if not aborted (e.g. user triggers another filter action before load completes)
321 if (filterText && filterText !== previousFilterText && !abortController.signal.aborted) {
322 dispatchFetch({type: 'filtering', filterText}, load);
323 }
324 } catch (e) {
325 dispatch({type: 'error', error: e as Error, abortController});
326 }
327 };
328
329 let didDispatchInitialFetch = useRef(false);
330 useEffect(() => {
331 if (!didDispatchInitialFetch.current) {
332 dispatchFetch({type: 'loading'}, load);
333 didDispatchInitialFetch.current = true;
334 }
335 // eslint-disable-next-line react-hooks/exhaustive-deps
336 }, []);
337
338 return {

Calls 2

createListActionsFunction · 0.90
dispatchFetchFunction · 0.85

Tested by 3

AsyncFilteringFunction · 0.72
AsyncComboBoxFunction · 0.72
AsyncListBoxFunction · 0.72