Skip to content

Commit b0c6faa

Browse files
authored
Enhance README with detailed library overview
Expanded the README to provide a comprehensive overview of the React Data List library, including usage examples and explanations of key concepts.
1 parent 51a0e8f commit b0c6faa

1 file changed

Lines changed: 97 additions & 11 deletions

File tree

README.md

Lines changed: 97 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,107 @@
11
# React Data List
22

3-
A library for composing data arrays using React components.
3+
React Data List is a library which helps you build data arrays by expressing items declaratively using React components. It was built primarily for React Native, but should work anywhere.
44

55
## Why?
66

7-
Universal List is an API for composing together lists.
8-
9-
In React Native world, virtualized lists are modelled with a flat array of data, along with a render function that describes how to render items. Most of our screens tend to be represented virtualized lists. It's a pillar to how we build.
10-
11-
However, building this data array can be really difficult. The straightforward approach is to simply have a dataFetchable that's the result of a single useNexusSelector call. However quickly becomes a problem when you want to have granular control over loading states (e.g. if we fail to load a single notification then don't poison the entire fetchable) or especially when you want to compose familiar data & render logic across screens (e.g. task picker items on the record detail page). When you need to solve both of those problems you quickly end up in a real mess with data selectors that are hundreds of lines long and not approachable.
12-
13-
Universal List allows you to model the creation of this data array in React JSX, encouraging the use of Suspense and Error Boundaries to achieve the behaviors you want. Nexus has first-class support for these wider React concepts, so the ergonomics are quite nice.
7+
For a full explanation around why this exists, please checkout the counterpart [article here](https://attio.com).
8+
9+
##
10+
11+
## How does it look?
12+
13+
### Example 1 - Basic
14+
15+
```tsx
16+
function ErrorOnRenderCheck() {
17+
return (
18+
<View
19+
onLayout={() => {
20+
throw new Error("This never happens as we evaluate descriptors before first paint.")
21+
}}
22+
/>
23+
)
24+
}
25+
26+
<ReactDataList
27+
renderer={
28+
<FlashListRenderer
29+
contentContainerStyle={contentContainerStyle}
30+
ListHeaderComponent={
31+
<Header
32+
toggleThorinAndCompany={toggleThorinAndCompany}
33+
jumbleFellowship={jumbleFellowship}
34+
/>
35+
}
36+
/>
37+
}
38+
renderEmpty={() => (
39+
/**
40+
* This never happens as we're guaranteed rows will be
41+
* evaluated to data items on first paint.
42+
*/
43+
<View style={styles.alert}>
44+
<ErrorOnRenderCheck />
45+
</View>
46+
)}
47+
>
48+
{/* Supports nested ReactDataList instances */}
49+
<ListHeaderDataListRow title="Places in Middle Earth" />
50+
<MiddleEarthPlacesDataListRow placeItems={MIDDLE_EARTH_PLACES} />
51+
52+
<ListHeaderDataListRow title="The Fellowship" />
53+
{fellowship.map((character) => (
54+
<CharacterListItemDataListRow
55+
key={character.name}
56+
name={character.name}
57+
race={character.race}
58+
url={character.url}
59+
/>
60+
))}
61+
62+
{isShowingThorinAndCompany && (
63+
<>
64+
<ListHeaderDataListRow title="Thorin and Company" />
65+
<React.Suspense fallback={<LoadingListItemDataListRow />}>
66+
<MiddleEarthHobbitCompanyDataListRows />
67+
</React.Suspense>
68+
</>
69+
)}
70+
</ReactDataList>
71+
```
1472

15-
## How does it work?
73+
https://github.com/user-attachments/assets/23c2d232-7f35-470e-98b4-156efaaf326a
74+
75+
### Example 2 - Fetchable Template
76+
77+
A lightweight wrapper around `ReactDataList` which provides a top-level [React.Suspense](https://react.dev/reference/react/Suspense) and [ErrorBoundary](https://react.dev/reference/react/Component#static-getderivedstatefromerror). This is useful for typical async work, where you may want to display skeleton rows (via `renderPending`), a full-screen spinner (via `renderPending`), or perhaps a full-screen error message (via `renderError`).
78+
79+
```tsx
80+
<ReactDataList.Fetchable
81+
renderer={
82+
<FlashListRenderer
83+
contentContainerStyle={contentContainerStyle}
84+
ListHeaderComponent={<Header reload={reload} />}
85+
/>
86+
}
87+
renderPendingRows={
88+
<>
89+
<ListHeaderDataListRow title="Thorin and Company" />
90+
<LoadingListItemDataListRow />
91+
<LoadingListItemDataListRow />
92+
<LoadingListItemDataListRow />
93+
<LoadingListItemDataListRow />
94+
<LoadingListItemDataListRow />
95+
<LoadingListItemDataListRow />
96+
</>
97+
}
98+
>
99+
<ListHeaderDataListRow title="Thorin and Company" />
100+
<MiddleEarthHobbitCompanyDataListRows key={reloadKey} />
101+
</ReactDataList.Fetchable>
102+
```
16103

17-
There are two main concepts: **row** and **renderer**.
18-
A **row** syncs some data and a render function to the list. The universal list then processes this into an aggregated data array, render function and other typical list functions. These then get passed into a renderer which takes the Universal List format and translates it into inputs for some list component, like FlashList. We refer to the item data that a row syncs as its **descriptor**
104+
https://github.com/user-attachments/assets/8ab7b63e-1ddc-40f9-8d20-6d443f21c934
19105

20106
## Release Process
21107

0 commit comments

Comments
 (0)