Skip to content

Commit c7eab40

Browse files
committed
Add new useMappingHelper hook for solving .map
1 parent 6cf6b8e commit c7eab40

File tree

4 files changed

+112
-0
lines changed

4 files changed

+112
-0
lines changed

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,36 @@ const MyList = () => {
181181
};
182182
```
183183

184+
- `useMappingHelper`: Returns a function that helps create optimal mapping keys for items when using `.map()` in your render methods. Using this ensures optimized recycling and performance for FlashList.
185+
186+
```jsx
187+
import { useMappingHelper } from "@shopify/flash-list";
188+
189+
const MyComponent = ({ items }) => {
190+
const { getMappingKey } = useMappingHelper();
191+
192+
return (
193+
<FlashList
194+
data={items}
195+
renderItem={({ item }) => <ItemComponent item={item} />}
196+
/>
197+
);
198+
};
199+
200+
// When mapping over items inside components:
201+
const NestedList = ({ items }) => {
202+
const { getMappingKey } = useMappingHelper();
203+
204+
return (
205+
<View>
206+
{items.map((item, index) => (
207+
<Text key={getMappingKey(index, item.id)}>{item.title}</Text>
208+
))}
209+
</View>
210+
);
211+
};
212+
```
213+
184214
- If you're nesting horizontal FlashLists in vertical lists, we highly recommend the vertical list to be FlashList too. We have optimizations to wait for child layout to complete which can improve load times.
185215
- For chat apps, consider increasing drawDistance to 500 or higher if you're going to add a lot of items to the top. Higher drawDistance can remove some flickers. 500-1000 for chat can be okay. We would like to hear from you if you run into issues.
186216
- Memoizing props passed to FlashList is more important in v2. v1 was more selective about updating items, but this was often perceived as a bug by developers. We will not follow that approach and will instead allow developers to ensure that props are memoized. We will stop re-renders of children wherever it is obvious.

documentation/docs/fundamentals/usage.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,67 @@ const GridItem = ({ item }) => {
617617
};
618618
```
619619

620+
### useMappingHelper
621+
622+
```tsx
623+
const { getMappingKey } = useMappingHelper();
624+
```
625+
626+
Returns a function that helps create a mapping key for items when using `.map()` in your render methods. Using this ensures that performance is optimal for FlashList by providing consistent keys that work with the recycling system.
627+
628+
The `getMappingKey` function takes two parameters:
629+
630+
- `index`: The index of the item in the array
631+
- `itemKey`: A unique identifier for the item (string, number, or bigint)
632+
633+
It returns the appropriate key value to use in the `key` prop based on the current context.
634+
635+
**Basic usage:**
636+
637+
```jsx
638+
import { useMappingHelper } from "@shopify/flash-list";
639+
640+
const MyComponent = ({ items }) => {
641+
const { getMappingKey } = useMappingHelper();
642+
643+
return (
644+
<View>
645+
{items.map((item, index) => (
646+
<Text key={getMappingKey(index, item.id)}>{item.title}</Text>
647+
))}
648+
</View>
649+
);
650+
};
651+
```
652+
653+
**When to use it:**
654+
655+
- When mapping over arrays to create lists of components inside FlashList items
656+
- When building nested components that render multiple items from an array
657+
- To ensure consistent key generation that works well with FlashList's recycling system
658+
659+
```jsx
660+
import { useMappingHelper } from "@shopify/flash-list";
661+
662+
const ProductList = ({ products }) => {
663+
const { getMappingKey } = useMappingHelper();
664+
665+
return (
666+
<View style={styles.container}>
667+
<Text style={styles.title}>Featured Products</Text>
668+
<View style={styles.grid}>
669+
{products.map((product, index) => (
670+
<ProductCard
671+
key={getMappingKey(index, product.id)}
672+
product={product}
673+
/>
674+
))}
675+
</View>
676+
</View>
677+
);
678+
};
679+
```
680+
620681
# FlashList methods
621682

622683
### `prepareForLayoutAnimationRender()`

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export {
4545
} from "./MasonryFlashList";
4646
export { useLayoutState } from "./recyclerview/hooks/useLayoutState";
4747
export { useRecyclingState } from "./recyclerview/hooks/useRecyclingState";
48+
export { useMappingHelper } from "./recyclerview/hooks/useMappingHelper";
4849
export { JSFPSMonitor, JSFPSResult } from "./benchmark/JSFPSMonitor";
4950
export { autoScroll, Cancellable } from "./benchmark/AutoScrollHelper";
5051
export { default as ViewToken } from "./viewability/ViewToken";
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { useCallback } from "react";
2+
3+
import { useRecyclerViewContext } from "../RecyclerViewContextProvider";
4+
5+
/**
6+
* Returns a function that can help create a mapping key for the items.
7+
* Useful when doing .map on items to create a list of components.
8+
* Using this ensures that performance is optimal for FlashList
9+
*/
10+
export const useMappingHelper = () => {
11+
const recyclerViewContext = useRecyclerViewContext();
12+
const getMappingKey = useCallback(
13+
(index: number, itemKey: string | number | bigint) => {
14+
return recyclerViewContext ? index : itemKey;
15+
},
16+
[recyclerViewContext]
17+
);
18+
19+
return { getMappingKey };
20+
};

0 commit comments

Comments
 (0)