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-demoimport { 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;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
ProductRowhas nouseStateof its own for the favorite status – it receivesisFavoriteas a ready-made value from outside and only reports a tap upward viaonToggleFavorite.Appis the "smart" side: it owns thefavoritesstate and the logic for how it changes –ProductRowdoesn't need to know any of that.
5. Outputs
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.