Use React hooks to manage app state and create dynamic, interactive mobile interfaces.
Creative apps are inherently interactive. When you:
All of this requires state management - tracking what's currently happening in your app.
State is data that can change over time. The useState
hook lets you add state to components:
import React, { useState } from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
function PhotoCounter() {
// State: current count, function to update it
const [photoCount, setPhotoCount] = useState(0);
const addPhoto = () => {
setPhotoCount(photoCount + 1);
};
return (
<View style={styles.container}>
<Text style={styles.count}>Photos: {photoCount}</Text>
<TouchableOpacity style={styles.button} onPress={addPhoto}>
<Text style={styles.buttonText}>Add Photo</Text>
</TouchableOpacity>
</View>
);
}
Build a photo selection interface:
import React, { useState } from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
function PhotoSelector() {
const [selectedPhotos, setSelectedPhotos] = useState([]);
const [selectionMode, setSelectionMode] = useState(false);
// Mock photo data
const photos = [
{ id: 1, name: 'Sunset' },
{ id: 2, name: 'Portrait' },
{ id: 3, name: 'Landscape' }
];
const togglePhoto = (photoId) => {
if (selectedPhotos.includes(photoId)) {
// Remove from selection
setSelectedPhotos(selectedPhotos.filter(id => id !== photoId));
} else {
// Add to selection
setSelectedPhotos([...selectedPhotos, photoId]);
}
};
return (
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.title}>Your Photos</Text>
<TouchableOpacity
onPress={() => setSelectionMode(!selectionMode)}
>
<Text style={styles.modeText}>
{selectionMode ? 'Cancel' : 'Select'}
</Text>
</TouchableOpacity>
</View>
{selectionMode && (
<Text style={styles.selectionCount}>
{selectedPhotos.length} selected
</Text>
)}
{photos.map(photo => (
<TouchableOpacity
key={photo.id}
style={[
styles.photo,
selectedPhotos.includes(photo.id) && styles.selected
]}
onPress={() => selectionMode && togglePhoto(photo.id)}
>
<Text style={styles.photoName}>{photo.name}</Text>
{selectedPhotos.includes(photo.id) && (
<Text style={styles.checkmark}>✓</Text>
)}
</TouchableOpacity>
))}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
backgroundColor: '#000',
},
header: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 20,
},
title: {
fontSize: 24,
fontWeight: 'bold',
color: 'white',
},
modeText: {
color: '#6366f1',
fontSize: 16,
},
selectionCount: {
color: '#9ca3af',
marginBottom: 16,
},
photo: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
padding: 16,
marginVertical: 4,
backgroundColor: '#1f2937',
borderRadius: 8,
},
selected: {
backgroundColor: '#374151',
borderWidth: 2,
borderColor: '#6366f1',
},
photoName: {
color: 'white',
fontSize: 16,
},
checkmark: {
color: '#6366f1',
fontSize: 18,
fontWeight: 'bold',
},
});
Components communicate through props. Here's how to share state:
import React, { useState } from 'react';
// Child component receives data via props
function PhotoDisplay({ photo, isSelected, onSelect }) {
return (
<TouchableOpacity
onPress={() => onSelect(photo.id)}
style={[styles.photo, isSelected && styles.selected]}
>
<Text>{photo.name}</Text>
</TouchableOpacity>
);
}
// Parent component manages state
function Gallery() {
const [selectedId, setSelectedId] = useState(null);
const photos = [{ id: 1, name: 'Sunset' }];
return (
<View>
{photos.map(photo => (
<PhotoDisplay
key={photo.id}
photo={photo}
isSelected={selectedId === photo.id}
onSelect={setSelectedId}
/>
))}
</View>
);
}
// Good: State in component that uses it
function EditingControls() {
const [brightness, setBrightness] = useState(50);
return <Slider value={brightness} onChange={setBrightness} />;
}
import React, { useState, useCallback } from 'react';
function PhotoGrid({ photos }) {
const [selectedIds, setSelectedIds] = useState([]);
// useCallback prevents re-creating function on each render
const handleSelect = useCallback((id) => {
setSelectedIds(prev =>
prev.includes(id)
? prev.filter(selectedId => selectedId !== id)
: [...prev, id]
);
}, []);
return (
// Render photos...
);
}
This state management enables your Creative Studio features:
You've mastered:
useState
for component stateNext: You'll learn how to work with images, camera access, and device permissions.