Zustand (state)
Dauer: 45 Minuten
- Checkbox hinzufügen
state
imTodo
verwenden- Verwendung von
state
nachvollziehen
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-checkbox
In 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:
state
gehört zu genau einer Komponente (und ist sozusagen „privat“).state
kann sich im Laufe der Zeit verändern.state
wird 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
useState
ausreact
(nichtreact-native
!) - Aufruf des Hooks
useState
in der Komponente, um denstate
zu initialisieren und eine Funktion zum Ändern desstate
zu erhalten. - Verwendung des
state
in 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 gleich
Der 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.).