Zustand (state)
Dauer: 30 Minuten
- Checkbox hinzufügen
stateimTodoverwenden- Verwendung von
statenachvollziehen
Die Prinzipien für state bzw. Zustand in
React Native sind ähnlich zu denen in Android
Compose und Flutter:
- Komponenten können einen Zustand haben
- Eine Änderung des Zustands einer Komponente bewirkt ein Neuzeichnen dieser Komponente (und ggf. der in ihr enthaltenen Komponenten)
Wir lernen den Umgang mit state in React
Native schrittweise kennen.
Checkbox hinzufügen
Ein Todo-Eintrag soll nun auch eine Checkbox enthalten. Expo hat eine große Auswahl von zusätzlichen Komponenten und APIs, die bei Bedarf unserer App hinzugefügt werden.
Siehe dazu die [Dokumentation der Expo Checkbox] (https://docs.expo.dev/versions/latest/sdk/checkbox/ ).
Checkbox-Package installieren:
npx expo install expo-checkboxIn der Todo-Komponenten die Checkbox verwenden:
import Checkbox from 'expo-checkbox';Wir müssen nun den UI-Code der Todo-Komponenten etwas anpassen, damit neben dem Text des Todos eine Checkbox dargestellt wird:
import { StyleSheet, Text, View } from 'react-native';
import Checkbox from 'expo-checkbox';
export default function Todo({ children }) {
return (
<View style={styles.container}>
<Checkbox style={styles.checkbox} />
<Text style={styles.todoText}>{children}</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 10,
},
checkbox: {
marginLeft: 10,
},
todoText: {
fontSize: 24,
width: '100%',
paddingHorizontal: 10,
marginBottom: 5,
},
});Wir verwenden hier ein View-Element, das
die Checkbox und den Text umgibt. Als
sogenanntes Container-Element definiert es
Flexbox-Styles, die die beiden Elemente
nebeneinander anordnet und vertikal zentriert.
Mehr zur Flexbox bei Bedarf später bzw. im
Videokurs.
Zustand in React Native
Bisher haben wir mit props gesehen, wie Komponenten mit
Eigenschaften zur Laufzeit konfiguriert werden können. Dabei können
die Eigenschaften bzw. props nicht innerhalb einer Komponente
verändert oder neu zugewiesen werden, d.h. sie sind „read only“.
Wenn sich nun eine Komponente im Laufe der Zeit verändern soll,
dann brauchen wir dafür eine andere Möglichkeit. Diese Möglichkeit
ist der Zustand bzw. state.
Bei der Verwendung von state gibt es zwei Dinge zu beachten:
stategehört zu genau einer Komponente (und ist sozusagen „privat“).statekann sich im Laufe der Zeit verändern.statewird ausschließlich mit einer zugehörigen Änderungsfunktion aktualisiert.
Wenn sich der state einer Komponente verändert, dann wird die
Komponente neu gerendert. Dies geschieht automatisch und muss nicht
von uns programmiert werden.
Standardmäßig ist eine Komponente in react zustandslos (stateless).
Wenn wir state verwenden wollen, dann müssen wir die Komponente
mit einem sogenannten Hook ausstatten, der den state verwaltet.
Für den state gibt es den Hook useState.
Hooks sind ein Konzept in React Native (und React), das es uns erlaubt,
Komponenten mit bestimmtem Verhalten zu versehen. Hooks sind Funktionen,
deren Name mit use beginnt.
Neben useState gibt es noch weitere Hooks und es ist auch möglich,
eigene Hooks zu schreiben.
Folgende Schritte sind nötig, um eine Komponente mit state
auszustatten:
- Importieren des Hooks
useStateausreact(nichtreact-native!) - Aufruf des Hooks
useStatein der Komponente, um denstatezu initialisieren und eine Funktion zum Ändern desstatezu erhalten. - Verwendung des
statein der Komponente
Zustand im Todo
Wir benötigen nun state in der Komponente Todo, damit wir den Zustand done (erledigt)
verwalten können (true oder false).
Importieren des Hooks useState
Zunächst importieren wir den Hooks useState aus react:
import { useState } from 'react'; // <-- import aus react!
import { StyleSheet, Text, View } from 'react-native';
import Checkbox from 'expo-checkbox';
// Der Rest bleibt gleichDer Hook useState steht uns nun zur Verfügung und wir können ihn
in der Komponente Todo verwenden.
Aufruf des Hooks useState zur Initialisierung des state
Um den state zu initialisieren und eine Funktion zum Ändern des
state zu erhalten, fügen wir der Komponente Todo folgenden Code
hinzu:
import { useState } from 'react'; // <-- import aus react!
import { StyleSheet, Text, View } from 'react-native';
import Checkbox from 'expo-checkbox';
export default function Todo({ children }) {
const [done, setDone] = useState(false); // <-- state mit false initialisieren
// Der Rest bleibt gleich
} Für die Intitialisierung des state rufen wir useState auf und
übergeben den initialen Wert des state als Argument. Für den initialen
Zustand können wir jeden Wert verwenden, den wir wollen. In unserem Fall
ist der initiale Wert false.
useState gibt uns ein Array mit zwei Elementen zurück. Das erste
Element ist die state-Variable mit dem aktuellen Wert des state
(zunächst false aufgrund der Initialisierung) und das zweite
Element ist eine Funktion, mit der wir den state ändern können
(„update function“). Diese Funktion heißt in unserem Fall setDone
— wir können die Funktion und die state-Variable beliebig
bezeichnen, aber diese Art der Benennung mit set ist üblich. Durch
eine Dekonstruktion des Arrays können wir die beiden Elemente direkt in
eine Variable und eine Funktion destrukturieren:
const [done, setDone] = useState(false);Live Coding: Eventuell die Destrukturierung des Arrays erklären.
Im Videokurs wird dies alles ausführlich gezeigt.
Verwendung des state
Wir haben nun den state initialisiert und eine Funktion zum Ändern
des state erhalten. Nun können wir den state in der Komponente
verwenden. Dazu definieren wir die Props value
und onValueChange der Checkbox passend zum state:
export default function Todo({ children }) {
const [done, setDone] = useState(false); // <-- state mit false initialisieren
return (
<View style={styles.container}>
<Checkbox
style={styles.checkbox}
value={done} // <-- Verwendung des state
onValueChange={setDone} // <-- Verwendung der update function
/>
<Text style={styles.todoText}>{children}</Text>
</View>
);
}Wir verwenden den state nun als Wert der Checkbox (erledigt oder nicht) und die
setDone-Funktion als onValueChange-Handler.
Wenn wir nun die Checkbox antippen, dann ändert sich der Zustand im Todo.
Jede Änderung des state führt zu einer Neudarstellung der Komponente,
d.h. die Komponente wird neu „gerendert“. Dies geschieht automatisch und
muss nicht von uns programmiert werden.
Achtung: Die Änderung des state erfolgt immer mit der
Änderungsfunktion (bei uns setDone). Wenn wir den state direkt
durch eine Zuweisung ändern (z.B. done = 'wrong!!!'), dann wird
die Komponente nicht neu gerendert und der state wird nicht aktualisiert.
Der state ist immer privat und gehört zu einer Komponente.
Wenn wir den state in einer anderen Komponente verwenden wollen,
dann müssen wir den state in die übergeordnete Komponente verschieben
und von dort an die untergeordnete Komponente weitergeben. Dies geschieht
mit props, die wir in der übergeordneten Komponente an die
untergeordnete Komponente übergeben.
Todo-Text antippbar mit Style passend zum Zustand
Wenn wir wie bei den vorigen Beispiel-Apps das ganze Todo antippbar machen wollen und das Todo im erledigten Zustand durchgestrichen darstellen wollen, dann könnte der Code so angepasst werden:
import { useState } from 'react'; // <-- import aus react!
import { Pressable, StyleSheet, Text, View } from 'react-native';
import Checkbox from 'expo-checkbox';
export default function Todo({ children }) {
const [done, setDone] = useState(false); // <-- state mit false initialisieren
const doneStyle = done
? { textDecorationLine: 'line-through' }
: {}; // <-- Styling abhängig vom state
return (
<Pressable onPress={() => setDone(!done)}>
<View style={styles.container}>
<Checkbox
style={styles.checkbox}
value={done} // <-- Verwendung des state
onValueChange={setDone} // <-- Verwendung der update function
/>
<Text style={[styles.todoText, doneStyle]}>{children}</Text>
</View>
</Pressable>
);
}Abhängig vom state in done definieren
wir einen doneStyle, der den Text eines Todos
im erledigten Status durchgestrichen darstellt.
In den React Native Docs gibt es mehr Infos zur Pressable-Komponente
Übung: Zähler
Wenn genügend Zeit vorhanden ist, dann könnten wir in dem Standardbeispiel wir in Expo Snack einen Zähler programmieren:

Hierzu kann direkt in App.js eine Text-Komponente mit einem
Button und einem state programmiert werden. Der state ist
eine Zahl, die bei jedem Klick auf den Button um eins erhöht wird.
Eventuell den Anfang gemeinsam und dann weitere Buttons hinzufügen (z.B. um 10 erhöhen, auf 0 zurücksetzen, usw.).
Lösung
import {useState} from 'react';
import { Button, Text, TextInput, SafeAreaView, StyleSheet } from 'react-native';
export default function App() {
const [counter,setCounter] = useState(0);
const [increment,setIncrement] = useState(1);
return (
<SafeAreaView style={styles.container}>
<Text style={styles.paragraph}>
{counter}
</Text>
<TextInput value={increment} onChangeText={(num)=>setIncrement(+num)} keyboardType='numeric'/>
<Button title="Zählen" onPress={() =>setCounter(counter+increment) }/>
<Button title="Um 10 erhöhen" onPress={() =>setCounter(counter+10) }/>
<Button title="Auf 0 zurücksetzen" onPress={() =>setCounter(0) }/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#ecf0f1',
padding: 8,
},
paragraph: {
margin: 24,
fontSize: 128,
color: 'orange',
textAlign: 'center',
},
});