Skip to main content

react-native-list-performance

Optimizes React Native FlatList and SectionList performance through windowing, item memoization, getItemLayout, and efficient rendering strategies for smooth scrolling.

Ir a la instalación

Datos de origen

Repositorio
paulpas/agent-skill-router
Última actividad en el origen
9 de junio de 2026 a las 16:28
Idioma detectado de SKILL.md
inglés
Estrellas
4
Forks
1

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
react-native-list-performance
description
Optimizes React Native FlatList and SectionList performance through windowing, item memoization, getItemLayout, and efficient rendering strategies for smooth scrolling.
license
MIT
compatibility
opencode
archetypes
["tactical","generation"]
anti_triggers
["brainstorming","vague ideation","long-form architecture"]
response_profile
{"verbosity":"low","directive_strength":"high","abstraction_level":"operational"}
metadata
{"version":"1.0.0","domain":"coding","triggers":"flatlist performance, react native list, list optimization, scroll performance, windowing, getItemLayout, flashlist","role":"implementation","scope":"implementation","output-format":"code","content-types":["code","guidance","do-dont","examples"],"related-skills":"react-native-animation, react-native-navigation, react-native-ui-patterns","author":"https://github.com/vercel-labs","source":"https://github.com/vercel-labs/agent-skills"}
# React Native List Performance Optimizes FlatList and SectionList rendering through windowed virtualization, fixed-size item layout measurements, memoized item components, and tuned batch rendering parameters. Achieves smooth 60fps scrolling even with thousands of items. ## TL;DR Checklist - [ ] Use FlatList (not ScrollView with map) for any list over 20 items - [ ] Extract list item components and wrap with React.memo - [ ] Implement getItemLayout for fixed-height items - [ ] Set windowSize (default 21) based on scroll smoothness vs. memory tradeoff - [ ] Use stable, unique keyExtractor (never index) - [ ] Profile scroll performance with built-in FPS monitor - [ ] Consider FlashList for lists exceeding 500 items --- ## When to Use Use this skill when: - Rendering any dynamic list exceeding 20 items - Building infinite-scroll feeds, chat threads, or data tables - Diagnosing scroll jank or dropped frames in long lists - Migrating from ScrollView + map() to virtualized lists - Displaying variable-height items (comments, cards with dynamic content) - Optimizing initial render time for lists with hundreds of items --- ## When NOT to Use Avoid this skill for: - Lists under 20 items with simple content — ScrollView is simpler and sufficient - Static content that never changes — consider ScrollView for clarity - Short forms or settings screens — FlatList overhead isn't justified - Navigation-based lists (use React Navigation's built-in optimized rendering) --- ## Core Workflow 1. **Choose the Right List Component** — FlatList for homogeneous items, SectionList for sectioned data, FlashList for extreme performance needs. 2. **Extract and Memoize Item Components** — Move renderItem logic to a standalone component wrapped with React.memo. **Checkpoint:** Verify the item component doesn't create new objects/arrays on each render. 3. **Configure getItemLayout** — Provide fixed item heights to skip measurement. **Checkpoint:** Confirm all items are the same height before using getItemLayout. 4. **Tune Virtualization Parameters** — Adjust windowSize, maxToRenderPerBatch, initialNumToRender, and removeClippedSubviews. 5. **Profile** — Enable the FPS monitor and verify 60fps during rapid scrolling. --- ## Implementation Patterns ### Pattern 1: Proper FlatList Setup (BAD vs. GOOD) ```tsx // ❌ BAD: Inline renderItem, no memo, index as key, no getItemLayout <FlatList data={items} renderItem={({ item }) => ( <View style={styles.item}> <Text>{item.name}</Text> <Text>{item.description}</Text> </View> )} keyExtractor={(_, index) => String(index)} /> ``` ```tsx // ✅ GOOD: Memoized item component, stable key, getItemLayout interface ListItemData { id: string; name: string; description: string; } const ListItem = React.memo(function ListItem({ item }: { item: ListItemData }) { return ( <View style={styles.item}> <Text style={styles.title}>{item.name}</Text> <Text style={styles.subtitle}>{item.description}</Text> </View> ); }); const ITEM_HEIGHT = 72; // Fixed height for all items function OptimizedList({ items }: { items: ListItemData[] }) { const renderItem = useCallback( ({ item }: { item: ListItemData }) => <ListItem item={item} />, [] ); return ( <FlatList data={items} renderItem={renderItem} keyExtractor={(item) => item.id} getItemLayout={(_, index) => ({ length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index, })} windowSize={15} maxToRenderPerBatch={10} initialNumToRender={12} removeClippedSubviews={true} /> ); } ``` ### Pattern 2: Avoiding Inline Object Creations in renderItem ```tsx // ❌ BAD: New style object created on every renderItem call <FlatList data={items} renderItem={({ item }) => ( <View style={{ padding: 16, backgroundColor: item.isActive ? '#eef' : '#fff' }}> <Text>{item.name}</Text> </View> )} /> ``` ```tsx // ✅ GOOD: Styles extracted, conditional styling via computed value const styles = StyleSheet.create({ item: { padding: 16 }, itemActive: { backgroundColor: '#eef' }, itemInactive: { backgroundColor: '#fff' }, }); const ListItem = React.memo(function ListItem({ item }: { item: ItemData }) { return ( <View style={[styles.item, item.isActive ? styles.itemActive : styles.itemInactive]}> <Text>{item.name}</Text> </View> ); }); ``` ### Pattern 3: Variable Height with getItemType ```tsx // ✅ GOOD: Dynamic item types for variable-height items type ListItemType = 'header' | 'message' | 'divider'; interface ChatItem { id: string; type: ListItemType; text?: string; sender?: string; } const ITEM_HEIGHTS: Record<ListItemType, number> = { header: 44, message: 80, divider: 24, }; function ChatList({ messages }: { messages: ChatItem[] }) { const getItemLayout = useCallback( (data: ArrayLike<ChatItem> | null, index: number) => { const item = data?.[index]; const length = ITEM_HEIGHTS[item?.type ?? 'message']; const offset = calculateOffset(data, index, ITEM_HEIGHTS); return { length, offset, index }; }, [] ); return ( <FlatList data={messages} getItemLayout={getItemLayout} keyExtractor={(item) => item.id} renderItem={renderChatItem} /> ); } // Helper: precompute offsets for variable heights function calculateOffset( data: ArrayLike<ChatItem> | null, index: number, heights: Record<string, number> ): number { let offset = 0; for (let i = 0; i < index; i++) { offset += heights[data?.[i]?.type ?? 'message']; } return offset; } ``` ### Pattern 4: FlashList for Extreme Performance ```tsx // ✅ GOOD: FlashList for lists over 500 items — better memory and scroll performance import { FlashList } from '@shopify/flash-list'; function LargeFeed({ posts }: { posts: Post[] }) { return ( <FlashList data={posts} renderItem={({ item }) => <PostCard post={item} />} keyExtractor={(item) => item.id} estimatedItemSize={120} getItemType={(item) => item.type} // Enables type-based reuse /> ); } ``` --- ## Constraints ### MUST DO - Use FlatList or FlashList for any dynamic list with more than 20 items - Implement `getItemLayout` when all items share the same height - Wrap list item components with `React.memo` to prevent unnecessary re-renders - Use `useCallback` for renderItem to avoid re-creating the function on every render - Use stable, unique keys in `keyExtractor` — never use the index - Extract styles and static objects outside the component to avoid re-creation - Set `removeClippedSubviews={true}` for lists with complex item layouts ### MUST NOT DO - Use ScrollView with `map()` for lists over 20 items — lacks windowing - Create new objects, arrays, or functions inside `renderItem` - Use the array index as the list item key - Set `windowSize` unnecessarily high (max 31) — consumes more memory - Inline styles or objects in renderItem — they're recreated on every render - Forget to memoize item components — they re-render on every parent update --- ## Related Skills | Skill | Purpose | |---|---| | `react-native-animation` | Animate list items with Reanimated for smooth transitions | | `react-native-navigation` | Navigate to list item detail screens with shared element transitions | | `react-native-ui-patterns` | Responsive list layouts with Flexbox and useWindowDimensions | --- ## Live References > Authoritative documentation links for this skill's domain. The model follows markdown links at load time to resolve external references and inline content. - [React Native FlatList Documentation](https://reactnative.dev/docs/flatlist) - [React Native SectionList Documentation](https://reactnative.dev/docs/sectionlist) - [React Native Performance Overview](https://reactnative.dev/docs/performance) - [Shopify FlashList Documentation](https://shopify.github.io/flash-list/) - [React Native FPS Monitor](https://reactnative.dev/docs/debugging#fps-monitor) - [Optimizing FlatList Configuration](https://reactnative.dev/docs/optimizing-flatlist-configuration) - [React.memo API Reference](https://react.dev/reference/react/memo)
Ver en GitHub