Skip to content
Back to skills

112 Typescript 7b9908e8

ASecurity

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

  • 9 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 31, 2026
developmenttypescriptreactperformance

Works with

  • cli

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned May 31, 2026

npx -y skills add tools-only/X-Skills --skill 112-typescript_7b9908e8 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 112 Typescript 7b9908e8?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 112 Typescript 7b9908e8
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-112-typescript-7b9908e8/badge)](https://www.skillsdirectory.com/skills/tools-only-112-typescript-7b9908e8)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# List Optimization

## Optimized FlatList

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

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 (
    <Pressable onPress={() => onPress(item.id)} style={styles.item}>
      <Text style={styles.title}>{item.title}</Text>
      <Text style={styles.subtitle}>{item.subtitle}</Text>
    </Pressable>
  );
});

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

  const renderItem: ListRenderItem<Item> = useCallback(
    ({ item }) => <ListItem item={item} onPress={handlePress} />,
    [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 (
    <FlatList
      data={data}
      renderItem={renderItem}
      keyExtractor={keyExtractor}
      getItemLayout={getItemLayout}
      // Performance props
      removeClippedSubviews
      maxToRenderPerBatch={10}
      windowSize={5}
      initialNumToRender={10}
      updateCellsBatchingPeriod={50}
    />
  );
}

const ITEM_HEIGHT = 72;
```

## SectionList

```typescript
import { SectionList } from 'react-native';

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

function GroupedList({ sections }: { sections: Section[] }) {
  const renderSectionHeader = useCallback(
    ({ section }: { section: Section }) => (
      <View style={styles.sectionHeader}>
        <Text style={styles.sectionTitle}>{section.title}</Text>
      </View>
    ),
    []
  );

  return (
    <SectionList
      sections={sections}
      renderItem={renderItem}
      renderSectionHeader={renderSectionHeader}
      keyExtractor={keyExtractor}
      stickySectionHeadersEnabled
    />
  );
}
```

## Pull to Refresh

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

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

  return (
    <FlatList
      data={data}
      renderItem={renderItem}
      refreshControl={
        <RefreshControl
          refreshing={refreshing}
          onRefresh={handleRefresh}
          tintColor="#007AFF"
        />
      }
    />
  );
}
```

## Infinite Scroll

```typescript
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 <ActivityIndicator style={styles.loader} />;
  }, [loading]);

  return (
    <FlatList
      data={data}
      renderItem={renderItem}
      onEndReached={loadMore}
      onEndReachedThreshold={0.5}
      ListFooterComponent={renderFooter}
    />
  );
}
```

## FlashList (Alternative)

```typescript
import { FlashList } from '@shopify/flash-list';

function FastList({ data }: { data: Item[] }) {
  return (
    <FlashList
      data={data}
      renderItem={renderItem}
      estimatedItemSize={72}
      keyExtractor={keyExtractor}
    />
  );
}
```

## Quick Reference

| Prop | Purpose |
|------|---------|
| `removeClippedSubviews` | Unmount off-screen items |
| `maxToRenderPerBatch` | Items per render batch |
| `windowSize` | Render window multiplier |
| `initialNumToRender` | Initial items to render |
| `getItemLayout` | Skip measurement (fixed height) |

| Optimization | When |
|--------------|------|
| `memo()` | All list items |
| `useCallback` | renderItem, keyExtractor |
| `getItemLayout` | Fixed height items |
| `FlashList` | Very large lists |

Files in this skill

  • README.md948 B
  • skill.md4.3 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.