All skills
Skillintermediate

List Optimization

```typescript import { FlatList, ListRenderItem } from 'react-native'; import { memo, useCallback } from 'react';

Claude Code Knowledge Pack7/10/2026

Overview

List Optimization

Optimized FlatList


interface Item {
  id: string;
  title: string;
  subtitle: string;
}

// Memoized list item
const ListItem = memo(function ListItem({
  item,
  onPress
}: {
  item: Item;
  onPress: (id: string) => void;
}) {
  return (
     onPress(item.id)} style={styles.item}>
      {item.title}
      {item.subtitle}
    
  );
});

function OptimizedList({ data }: { data: Item[] }) {
  // Memoize callbacks
  const handlePress = useCallback((id: string) => {
    console.log('Selected:', id);
  }, []);

  const renderItem: ListRenderItem = useCallback(
    ({ item }) => ,
    [handlePress]
  );

  const keyExtractor = useCallback((item: Item) => item.id, []);

  // Fixed height for getItemLayout
  const getItemLayout = useCallback(
    (_: any, index: number) => ({
      length: ITEM_HEIGHT,
      offset: ITEM_HEIGHT * index,
      index,
    }),
    []
  );

  return (
    
  );
}

const ITEM_HEIGHT = 72;

SectionList


interface Section {
  title: string;
  data: Item[];
}

function GroupedList({ sections }: { sections: Section[] }) {
  const renderSectionHeader = useCallback(
    ({ section }: { section: Section }) => (
      
        {section.title}
      
    ),
    []
  );

  return (
    
  );
}

Pull to Refresh

function RefreshableList({ data, onRefresh }: Props) {
  const [refreshing, setRefreshing] = useState(false);

  const handleRefresh = useCallback(async () => {
    setRefreshing(true);
    await onRefresh();
    setRefreshing(false);
  }, [onRefresh]);

  return (
    
      }
    />
  );
}

Infinite Scroll

function InfiniteList() {
  const [data, setData] = useState<Item[]>([]);
  const [loading, setLoading] = useState(false);
  const [hasMore, setHasMore] = useState(true);

  const loadMore = useCallback(async () => {
    if (loading || !hasMore) return;

    setLoading(true);
    const newItems = await fetchMoreItems(data.length);

    if (newItems.length === 0) {
      setHasMore(false);
    } else {
      setData(prev => [...prev, ...newItems]);
    }
    setLoading(false);
  }, [data.length, loading, hasMore]);

  const renderFooter = useCallback(() => {
    if (!loading) return null;
    return ;
  }, [loading]);

  return (
    
  );
}

FlashList (Alternative)


function FastList({ data }: { data: Item[] }) {
  return (
    
  );
}

Quick Reference

PropPurpose
removeClippedSubviewsUnmount off-screen items
maxToRenderPerBatchItems per render batch
windowSizeRender window multiplier
initialNumToRenderInitial items to render
getItemLayoutSkip measurement (fixed height)
OptimizationWhen
memo()All list items
useCallbackrenderItem, keyExtractor
getItemLayoutFixed height items
FlashListVery large lists