Komponenten-Grundlagen

20 MinutenDie Bausteine von React Native kennenlernen

React Native und Expo

React Native ist ein Open-Source-Framework von Meta für Apps auf Android und iOS. Programmiert wird in JavaScript oder TypeScript mit React.

  • Komponenten wie View und Text werden zu echten nativen UI-Elementen von Android bzw. iOS
  • dadurch wirken Header, Ladeanzeige oder Schalter wie auf der Plattform gewohnt
  • der JavaScript-Code läuft in einer eigenen Engine (Hermes) auf dem Gerät
  • Expo ist das Framework rund um React Native: Projektvorlage, Navigation, Werkzeuge, Bibliotheken

Expo Snack

Expo Snack ist eine Entwicklungsumgebung für React Native im Browser.

  • Code links, Vorschau rechts: Android, iOS oder Web
  • App auf dem Handy öffnen: QR-Code mit der App Expo Go scannen
  • ideal zum Ausprobieren einzelner Komponenten

Projekt anlegen

Voraussetzung: Node.js (LTS), Git und VS Code mit der Extension Expo Tools.

npx create-expo-app@latest WeatherReactNativeTIF24 --template default@sdk-57
cd WeatherReactNativeTIF24
npm run reset-project
npx expo lint
npx expo start

Projektstruktur

Der Code liegt in src/, nach Aufgaben in Ordner aufgeteilt.

src/
├── app/         Routen (Screens), _layout.tsx
├── ui/          Komponenten, Hooks (ViewModels), Theme
├── model/       Datenmodell: City, CurrentWeather
└── data/        Datenquellen: Fake-Daten, Repositorys
    └── api/     DTOs für die API (ab Schritt 9)
app.json         Name, Icon, Einstellungen der App
package.json     Abhängigkeiten und Skripte

Komponenten

In React ist alles eine Komponente: eine Funktion, die beschreibt, was angezeigt wird.

import { Text, View } from 'react-native';

export function WeatherScreen() {
  return (
    <View>
      <Text>Lörrach</Text>
      <Text>14 °C</Text>
    </View>
  );
}

Komponenten

Fast Refresh: Speichern genügt, die Änderung ist sofort im Emulator.

  • Fast Refresh (Speichern): Code neu laden, State bleibt erhalten
  • Reload (r im Terminal): App neu laden, State geht verloren
  • neuer Build nötig bei nativen Änderungen, nicht in Expo Go

Layouts mit Flexbox

Jede View ist ein Flexbox-Container. Ohne weitere Angabe stehen die Kinder untereinander.

  • flexDirection: 'column' (Standard): untereinander
  • flexDirection: 'row': nebeneinander
  • justifyContent: Verteilung entlang der Hauptachse
  • alignItems: Ausrichtung quer zur Hauptachse
  • flex: 1: nimmt den freien Platz ein

Layouts mit Flexbox

Die Verschachtelung im Code entspricht der Verschachtelung auf dem Bildschirm.

Layout als verschachtelte Views: Bildschirm und Code haben denselben Aufbau
Layout als verschachtelte Views: Bildschirm und Code haben denselben Aufbau

Layouts mit Flexbox

<View style={styles.card}>
  <Text style={styles.city}>Lörrach</Text>
  <Text style={styles.emoji}>⛅</Text>
  <Text style={styles.temperature}>14 °C</Text>
  <View style={styles.row}>
    <Text>Wind: 8 km/h</Text>
    <Text>Teilweise bewölkt</Text>
  </View>
</View>

Abstände und Hintergrund

Statt Modifier gibt es die Eigenschaft style, gesammelt in einem StyleSheet am Ende der Datei.

const styles = StyleSheet.create({
  card: {
    margin: 16, // außen
    padding: 24, // innen
    borderRadius: 24,
    backgroundColor: '#BBDEFB',
    alignItems: 'center',
  },
  // city, emoji, temperature, row …
});

Datenmodell mit Typen

Statt fester Texte bekommen Komponenten nun Daten als Props. Die Form der Daten beschreiben Typen in TypeScript.

export type City = {
  name: string;
  latitude: number;
  longitude: number;
};

Datenmodell mit Typen

Komponenten sollten Daten als Props erhalten und sie nicht eigenständig holen.

type CurrentWeatherCardProps = {
  city: City;
  weather: CurrentWeather;
};

function CurrentWeatherCard({ city, weather }: CurrentWeatherCardProps) {
  return (
    <View style={styles.card}>
      <Text style={styles.city}>{city.name}</Text>
      {/* ... Emoji, Temperatur, Wind und Wetterlage */}
    </View>
  );
}

Header mit Expo Router

Den Header zeigt der Stack aus dem Layout. Jeder Screen setzt seinen Titel selbst.

export function WeatherScreen({ city, weather }: WeatherScreenProps) {
  return (
    <ScrollView>
      <Stack.Screen options={{ title: city.name }} />
      <CurrentWeatherCard city={city} weather={weather} />
    </ScrollView>
  );
}

Übung: Karte gestalten

  • Farben, Abstände und Schriftgrößen der Karte ändern, mit Fast Refresh ausprobieren
  • Bonus: neue Prop highlighted, die die Karte mit einem Rahmen hervorhebt