Skip to content

Commit a8373db

Browse files
authored
Async combobox and useAsyncList docs (#1572)
1 parent 7f9dc7f commit a8373db

File tree

2 files changed

+84
-2
lines changed

2 files changed

+84
-2
lines changed

packages/@react-spectrum/combobox/docs/ComboBox.mdx

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,53 @@ If a description is added, the prop `slot="description"` must be used to disting
516516
</ComboBox>
517517
```
518518

519+
## Asynchronous loading
520+
521+
ComboBox supports loading data asynchronously, and will display a progress circle reflecting the current load state,
522+
set by the `loadingState` prop. It also supports infinite scrolling to load more data on demand as the user scrolls, via the `onLoadMore` prop.
523+
524+
This example uses the [useAsyncList](../react-stately/useAsyncList.html) hook to handle loading the data.
525+
See the docs for more information.
526+
527+
```tsx example
528+
import {useAsyncList} from '@react-stately/data';
529+
530+
function AsyncLoadingExample() {
531+
let list = useAsyncList({
532+
async load({signal, cursor, filterText}) {
533+
if (cursor) {
534+
cursor = cursor.replace(/^http:\/\//i, 'https://');
535+
}
536+
537+
// If no cursor is available, then we're loading the first page,
538+
// filtering the results returned via a query string that
539+
// mirrors the ComboBox input text.
540+
// Otherwise, the cursor is the next URL to load,
541+
// as returned from the previous page.
542+
let res = await fetch(cursor || `https://swapi.dev/api/people/?search=${filterText}`, {signal});
543+
let json = await res.json();
544+
545+
return {
546+
items: json.results,
547+
cursor: json.next
548+
};
549+
}
550+
});
551+
552+
return (
553+
<ComboBox
554+
label="Star Wars Character Lookup"
555+
items={list.items}
556+
inputValue={list.filterText}
557+
onInputChange={list.setFilterText}
558+
loadingState={list.loadingState}
559+
onLoadMore={list.loadMore}>
560+
{item => <Item key={item.name}>{item.name}</Item>}
561+
</ComboBox>
562+
);
563+
}
564+
```
565+
519566
## Validation
520567
ComboBox can display a validation state to communicate to the user whether the current value is valid or invalid.
521568
Implement your own validation logic in your app and pass either `"valid"` or `"invalid"` to the ComboBox via the `validationState` prop.
@@ -584,7 +631,7 @@ function Example() {
584631
width="size-3000"
585632
label="To:"
586633
items={filteredItems}
587-
inputValue={filterValue}
634+
value={filterValue}
588635
onInputChange={setFilterValue}
589636
placeholder="Enter recipient email"
590637
allowsCustomValue>

packages/@react-stately/data/docs/useAsyncList.mdx

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ keywords: [lists, async loading, infinite loading, state]
2929

3030
## Introduction
3131

32-
`useAsyncList` extends on [useListData](useListData.html), adding support for async loading, pagination, and sorting.
32+
`useAsyncList` extends on [useListData](useListData.html), adding support for async loading, pagination, sorting, and filtering.
3333
It manages loading and error states, supports abortable requests, and works with any data fetching library or the built-in
3434
browser [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) API.
3535

@@ -174,6 +174,41 @@ let list = useAsyncList({
174174
});
175175
```
176176

177+
## Filtering
178+
179+
There are many instances where your list of data may need to be filtered, such as during user lookup or query searches.
180+
For server side filtering, this can be implemented by using the `filterText` option passed to the `load` function.
181+
The `setFilterText` method updates the current `filterText` value and triggers the `load` function. This allows
182+
you to reload the results with the new filter text.
183+
184+
### Server side filtering
185+
186+
The example below shows how server side filtering could be implemented by using `filterText` in the `load` function and passing a parameter to the API.
187+
The input value of the ComboBox is controlled by providing `list.filterText` as the ComboBox's `inputValue` prop, and `list.setFilterText` as the `onInputChange` prop.
188+
The `loadingState` prop is also used to show the appropriate loading indicator depending on the state of the list.
189+
190+
```tsx
191+
let list = useAsyncList({
192+
async load({signal, filterText}) {
193+
let res = await fetch(`https://swapi.dev/api/people/?search=${filterText}`, {signal});
194+
let json = await res.json();
195+
196+
return {
197+
items: json.results
198+
};
199+
}
200+
});
201+
202+
<ComboBox
203+
label="Star Wars Character Lookup"
204+
items={list.items}
205+
inputValue={list.filterText}
206+
onInputChange={list.setFilterText}
207+
loadingState={list.loadingState}>
208+
{item => <Item key={item.name}>{item.name}</Item>}
209+
</ComboBox>
210+
```
211+
177212
## Pre-selecting items
178213

179214
`useAsyncList` manages selection state for the list in addition to its data. If you need to programmatically select items

0 commit comments

Comments
 (0)