DEV Community

Aman Hussain Shaikh
Aman Hussain Shaikh

Posted on

Why Use FlatList Instead of Traditional Map in React Native?

Introduction

Hey there, React Native developer! πŸ‘‹

If you're building mobile apps, you've probably faced this situation: you have a list of data (maybe users, products, or posts) and you need to display them on the screen. Your first instinct might be to use the traditional JavaScript map() function. But wait! There's a better way called FlatList, and in this guide, I'll show you exactly why it's a game-changer.

The Problem with Traditional Map

Let's start by understanding what happens when you use the regular map() function to render lists.

Example: Using Map (The Traditional Way)

import React from 'react';
import { View, Text, ScrollView, StyleSheet } from 'react-native';

const App = () => {
  // Let's say we have 1000 users
  const users = Array.from({ length: 1000 }, (_, i) => ({
    id: i,
    name: `User ${i + 1}`,
    email: `user${i + 1}@example.com`
  }));

  return (
    <ScrollView style={styles.container}>
      {users.map(user => (
        <View key={user.id} style={styles.userCard}>
          <Text style={styles.name}>{user.name}</Text>
          <Text style={styles.email}>{user.email}</Text>
        </View>
      ))}
    </ScrollView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 10,
  },
  userCard: {
    padding: 15,
    marginBottom: 10,
    backgroundColor: '#f0f0f0',
    borderRadius: 8,
  },
  name: {
    fontSize: 18,
    fontWeight: 'bold',
  },
  email: {
    fontSize: 14,
    color: '#666',
  },
});

export default App;
Enter fullscreen mode Exit fullscreen mode

What's Wrong with This Approach?

When you use map(), React Native does the following:

  1. Renders ALL items at once - Even if you have 10,000 items, it tries to create components for every single one
  2. Keeps everything in memory - All 10,000 components stay in memory, eating up your device's RAM
  3. Slow initial load - The app freezes while rendering thousands of items
  4. Poor scrolling performance - The app becomes laggy and unresponsive
  5. Battery drain - Your phone works harder, draining battery faster

Real-world impact: Imagine scrolling through Instagram with 10,000 posts all loaded at once. Your phone would crash! πŸ“±πŸ’₯

The Solution: FlatList

FlatList is a smart component that only renders what you can see on the screen. It's like having a smart waiter who only brings food to tables with customers, instead of filling every table in an empty restaurant.

Example: Using FlatList (The Smart Way)

import React from 'react';
import { View, Text, FlatList, StyleSheet } from 'react-native';

const App = () => {
  // Same 1000 users
  const users = Array.from({ length: 1000 }, (_, i) => ({
    id: i.toString(), // FlatList needs string IDs
    name: `User ${i + 1}`,
    email: `user${i + 1}@example.com`
  }));

  // This function renders each item
  const renderItem = ({ item }) => (
    <View style={styles.userCard}>
      <Text style={styles.name}>{item.name}</Text>
      <Text style={styles.email}>{item.email}</Text>
    </View>
  );

  return (
    <FlatList
      data={users}
      renderItem={renderItem}
      keyExtractor={item => item.id}
      style={styles.container}
    />
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 10,
  },
  userCard: {
    padding: 15,
    marginBottom: 10,
    backgroundColor: '#f0f0f0',
    borderRadius: 8,
  },
  name: {
    fontSize: 18,
    fontWeight: 'bold',
  },
  email: {
    fontSize: 14,
    color: '#666',
  },
});

export default App;
Enter fullscreen mode Exit fullscreen mode

How FlatList Works (Simple Explanation)

Think of FlatList like a magic window:

  • You can only see through the window (your phone screen)
  • FlatList only renders items in the window (visible items + a few above and below)
  • When you scroll, old items disappear and new ones appear
  • Invisible items are removed from memory

This is called "Virtualization" or "Lazy Loading".

Visual Representation

Total Items: 1000
Screen shows: 10 items

Map Method:
[Renders ALL 1000 items] ❌ Slow and heavy

FlatList Method:
[Renders only 10-15 items] βœ… Fast and light
As you scroll β†’ Old items removed, new items added
Enter fullscreen mode Exit fullscreen mode

Key Differences: Map vs FlatList

Feature Map Method FlatList
Initial Render All items at once Only visible items
Memory Usage High (keeps everything) Low (removes invisible items)
Performance Slow with large lists Fast with any size list
Scrolling Laggy Smooth
Battery Usage High Optimized
Best For Small lists (< 50 items) Large lists (any size)

Essential FlatList Props Explained

Let's break down the important props you'll use:

1. data (Required)

The array of items you want to display.

<FlatList data={users} />
Enter fullscreen mode Exit fullscreen mode

2. renderItem (Required)

A function that tells FlatList how to display each item.

const renderItem = ({ item, index }) => (
  <Text>{item.name} - Position {index}</Text>
);
Enter fullscreen mode Exit fullscreen mode

3. keyExtractor (Required)

Gives each item a unique ID so React can track them efficiently.

keyExtractor={item => item.id}
// or
keyExtractor={(item, index) => index.toString()}
Enter fullscreen mode Exit fullscreen mode

4. ItemSeparatorComponent (Optional)

Adds a divider between items.

const Separator = () => <View style={{ height: 1, backgroundColor: '#ccc' }} />;

<FlatList
  data={users}
  renderItem={renderItem}
  ItemSeparatorComponent={Separator}
/>
Enter fullscreen mode Exit fullscreen mode

5. ListHeaderComponent (Optional)

Adds content at the top of the list.

<FlatList
  data={users}
  renderItem={renderItem}
  ListHeaderComponent={<Text style={styles.header}>User List</Text>}
/>
Enter fullscreen mode Exit fullscreen mode

6. ListEmptyComponent (Optional)

Shows content when the list is empty.

<FlatList
  data={users}
  renderItem={renderItem}
  ListEmptyComponent={<Text>No users found</Text>}
/>
Enter fullscreen mode Exit fullscreen mode

Complete Real-World Example

Here's a practical example with all the bells and whistles:

import React, { useState } from 'react';
import { 
  View, 
  Text, 
  FlatList, 
  StyleSheet, 
  ActivityIndicator,
  RefreshControl 
} from 'react-native';

const App = () => {
  const [users, setUsers] = useState(
    Array.from({ length: 100 }, (_, i) => ({
      id: i.toString(),
      name: `User ${i + 1}`,
      email: `user${i + 1}@example.com`,
      avatar: `https://i.pravatar.cc/150?img=${i + 1}`
    }))
  );

  const [refreshing, setRefreshing] = useState(false);

  // Pull to refresh functionality
  const onRefresh = () => {
    setRefreshing(true);
    // Simulate API call
    setTimeout(() => {
      setRefreshing(false);
    }, 2000);
  };

  // Render each user
  const renderItem = ({ item, index }) => (
    <View style={styles.userCard}>
      <View style={styles.avatar}>
        <Text style={styles.avatarText}>{item.name[0]}</Text>
      </View>
      <View style={styles.userInfo}>
        <Text style={styles.name}>{item.name}</Text>
        <Text style={styles.email}>{item.email}</Text>
      </View>
    </View>
  );

  // Header component
  const ListHeader = () => (
    <View style={styles.headerContainer}>
      <Text style={styles.headerTitle}>All Users</Text>
      <Text style={styles.headerSubtitle}>Total: {users.length}</Text>
    </View>
  );

  // Empty list component
  const ListEmpty = () => (
    <View style={styles.emptyContainer}>
      <Text style={styles.emptyText}>No users available</Text>
    </View>
  );

  // Separator between items
  const ItemSeparator = () => <View style={styles.separator} />;

  // Footer component (loading more)
  const ListFooter = () => (
    <View style={styles.footer}>
      <ActivityIndicator size="small" color="#007AFF" />
      <Text style={styles.footerText}>Loading more...</Text>
    </View>
  );

  return (
    <FlatList
      data={users}
      renderItem={renderItem}
      keyExtractor={item => item.id}
      ItemSeparatorComponent={ItemSeparator}
      ListHeaderComponent={ListHeader}
      ListEmptyComponent={ListEmpty}
      ListFooterComponent={ListFooter}
      refreshControl={
        <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
      }
      style={styles.container}
      contentContainerStyle={styles.contentContainer}
      // Performance optimizations
      removeClippedSubviews={true}
      maxToRenderPerBatch={10}
      updateCellsBatchingPeriod={50}
      initialNumToRender={10}
      windowSize={10}
    />
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
  },
  contentContainer: {
    padding: 15,
  },
  headerContainer: {
    padding: 20,
    backgroundColor: '#007AFF',
    borderRadius: 10,
    marginBottom: 15,
  },
  headerTitle: {
    fontSize: 24,
    fontWeight: 'bold',
    color: 'white',
  },
  headerSubtitle: {
    fontSize: 14,
    color: 'white',
    marginTop: 5,
  },
  userCard: {
    flexDirection: 'row',
    padding: 15,
    backgroundColor: 'white',
    borderRadius: 10,
    alignItems: 'center',
  },
  avatar: {
    width: 50,
    height: 50,
    borderRadius: 25,
    backgroundColor: '#007AFF',
    justifyContent: 'center',
    alignItems: 'center',
    marginRight: 15,
  },
  avatarText: {
    color: 'white',
    fontSize: 20,
    fontWeight: 'bold',
  },
  userInfo: {
    flex: 1,
  },
  name: {
    fontSize: 16,
    fontWeight: '600',
    color: '#333',
  },
  email: {
    fontSize: 14,
    color: '#666',
    marginTop: 4,
  },
  separator: {
    height: 10,
  },
  emptyContainer: {
    padding: 50,
    alignItems: 'center',
  },
  emptyText: {
    fontSize: 16,
    color: '#999',
  },
  footer: {
    padding: 20,
    alignItems: 'center',
  },
  footerText: {
    marginTop: 10,
    color: '#666',
  },
});

export default App;
Enter fullscreen mode Exit fullscreen mode

Performance Optimization Tips

Want to make your FlatList even faster? Use these props:

<FlatList
  data={data}
  renderItem={renderItem}
  keyExtractor={item => item.id}

  // Only render 10 items initially
  initialNumToRender={10}

  // How many items to render per batch
  maxToRenderPerBatch={10}

  // How often to batch render (ms)
  updateCellsBatchingPeriod={50}

  // Number of screens to render above/below
  windowSize={5}

  // Remove items far from viewport (Android)
  removeClippedSubviews={true}

  // Enable memory optimization
  getItemLayout={(data, index) => (
    { length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index }
  )}
/>
Enter fullscreen mode Exit fullscreen mode

When Should You Use Map?

Don't completely abandon map()! It's still useful for:

  • Small, static lists (less than 20-30 items)
  • Lists that don't scroll (like a navigation menu)
  • Simple UI elements (like rendering buttons or tags)

Example of when map is fine:

// This is perfectly okay
const tags = ['React', 'Native', 'FlatList'];

<View>
  {tags.map(tag => (
    <Text key={tag}>{tag}</Text>
  ))}
</View>
Enter fullscreen mode Exit fullscreen mode

Common Mistakes to Avoid

❌ Mistake 1: Not using keyExtractor

// Bad - causes performance issues
<FlatList data={users} renderItem={renderItem} />
Enter fullscreen mode Exit fullscreen mode
// Good - provides unique keys
<FlatList 
  data={users} 
  renderItem={renderItem}
  keyExtractor={item => item.id}
/>
Enter fullscreen mode Exit fullscreen mode

❌ Mistake 2: Creating functions inside render

// Bad - creates new function every render
<FlatList
  data={users}
  renderItem={({ item }) => <UserCard user={item} />}
/>
Enter fullscreen mode Exit fullscreen mode
// Good - uses stable reference
const renderItem = ({ item }) => <UserCard user={item} />;

<FlatList data={users} renderItem={renderItem} />
Enter fullscreen mode Exit fullscreen mode

❌ Mistake 3: Not memoizing complex items

// Bad - re-renders all items on any change
const UserCard = ({ user }) => (
  <View>
    <Text>{user.name}</Text>
  </View>
);
Enter fullscreen mode Exit fullscreen mode
// Good - only re-renders when props change
const UserCard = React.memo(({ user }) => (
  <View>
    <Text>{user.name}</Text>
  </View>
));
Enter fullscreen mode Exit fullscreen mode

Quick Comparison Summary

Use Map When:

  • List has less than 20-30 items
  • Items are simple (single line of text)
  • List doesn't need to scroll
  • You need quick prototyping

Use FlatList When:

  • List has more than 30 items
  • List can grow dynamically
  • You need smooth scrolling
  • Performance matters
  • You're building production apps

Conclusion

FlatList is your best friend when building React Native apps with lists. It's:

  • Faster - Only renders what you see
  • Smarter - Automatically manages memory
  • Smoother - Provides buttery scrolling
  • Better - Comes with built-in features like pull-to-refresh

While the traditional map() method might seem simpler at first, FlatList is the professional choice for real-world apps. Your users will thank you for the smooth, lag-free experience!

Start using FlatList today, and watch your app's performance soar! πŸš€

Additional Resources

Happy coding! πŸ’»βœ¨

Top comments (0)