Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Dumb Components in React Native: Presentational vs. Smart

Dumb Components

~9 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026

"Dumb" (or "presentational") vs. "smart" (or "container") is an architectural pattern that clearly separates responsibilities within a React Native app: WHAT gets displayed, separate from WHERE the data comes from.

1. Description

A "dumb component" (also called a "presentational component") knows ONLY its props – it has no data access of its own (no fetch(), no AsyncStorage), no complex state of its own, and knows nothing about the app as a whole. It receives data passed in and reports events outward via callback props. The counterpart is a "smart component" (container), which loads/manages data and distributes it to several dumb components.

2. Short example

// Dumb component: only knows its props, no data logic of its own
function ProductRow({ name, price, onPress }) {
  return (
    <TouchableOpacity onPress={onPress}>
      <Text>{name} – ${price}</Text>
    </TouchableOpacity>
  );
}

3. Complete project: smart + dumb combined

npx create-expo-app dumb-components-demo
cd dumb-components-demo
components/ProductRow.js
import { Text, TouchableOpacity, StyleSheet } from 'react-native';

// DUMB: no idea where the data comes from, no state of its own
function ProductRow({ name, price, isFavorite, onToggleFavorite }) {
  return (
    <TouchableOpacity style={styles.row} onPress={onToggleFavorite}>
      <Text>{isFavorite ? '★' : '☆'} {name} – ${price.toFixed(2)}</Text>
    </TouchableOpacity>
  );
}

const styles = StyleSheet.create({
  row: { paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: '#e5e7eb' },
});

export default ProductRow;
App.js
import { useState } from 'react';
import { View, FlatList, StyleSheet } from 'react-native';
import ProductRow from './components/ProductRow';

// SMART: knows the data source (a fixed array here, e.g. an API in real apps) and the state
const PRODUCTS = [
  { id: '1', name: 'Hiking Boots', price: 89.99 },
  { id: '2', name: 'Backpack', price: 59.5 },
];

export default function App() {
  const [favorites, setFavorites] = useState([]);

  function toggleFavorite(id) {
    setFavorites((current) =>
      current.includes(id) ? current.filter((f) => f !== id) : [...current, id]
    );
  }

  return (
    <View style={styles.container}>
      <FlatList
        data={PRODUCTS}
        keyExtractor={(item) => item.id}
        renderItem={({ item }) => (
          <ProductRow
            name={item.name}
            price={item.price}
            isFavorite={favorites.includes(item.id)}
            onToggleFavorite={() => toggleFavorite(item.id)}
          />
        )}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, paddingTop: 60, paddingHorizontal: 16 },
});

4. Explanation

  • ProductRow has no useState of its own for the favorite status – it receives isFavorite as a ready-made value from outside and only reports a tap upward via onToggleFavorite.
  • App is the "smart" side: it owns the favorites state and the logic for how it changes – ProductRow doesn't need to know any of that.

5. Outputs

Ausgabe
Two rows ("☆ Hiking Boots – $89.99" and "☆ Backpack – $59.50"). Tapping a row fills in the star (★) and marks that product as a favorite, without affecting the other row.

Tipp: The benefit: ProductRow can be reused in ANY other list – even one whose data comes from a real API instead of a fixed array – without changing a single line inside ProductRow.js itself.