Einstieg in React Native

Start mit React Native.

Voraussetzungen

node.js und VSCode sind installiert.

Setup

Einrichtung des Environments und setup https://reactnative.dev/docs/environment-setup

mkdir -p ~/projects/
cd ~/projects/
npx react-native init MyTestApp

"react": "16.11.0",
"react-native": "^0.62.2" <<<<<<

best practices

  • git, backups

Warnungen

  • keine updates mittels --force umsetzen, sonst droht ein disaster

Plattform abhängiges Setups

https://reactnative.dev/docs/integration-with-existing-apps

  • icons
  • resource generator mit imagemagick "build-assets": "pushd raw && ./build_assets.sh",

Android

    ./android/app/src/main/res/

    android/app/src/main/res/mipmap-hdpi
    android/app/src/main/res/mipmap-mdpi
    android/app/src/main/res/mipmap-xhdpi
    android/app/src/main/res/mipmap-xxhdpi
    android/app/src/main/res/mipmap-xxxhdpi

android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png android/app/src/main/res/mipmap-hdpi/ic_launcher.png

iOS

ios/MyTestApp/Images.xcassets/AppIcon.appiconset

icon_app@2x.png
icon_app@3x.png
icon_notification@2x.png
icon_notification@3x.png
icon_settings@2x.png
icon_settings@3x.png
icon_spotlight@2x.png
icon_spotlight@3x.png
icon_store.png

xcode öffnen und drag & drop

IMAGE

Sonst DOWNLOAD: ios/MyTestApp/Images.xcassets/AppIcon.appiconset/Contents.json

Coding

Bester Start: https://reactnative.dev/docs/tutorial.html https://reactnative.dev/docs/getting-started

resources mkdir -p ~/projects/MyTestApp/resources

custom code: mkdir -p ~/projects/MyTestApp/src

    import {AppRegistry} from 'react-native';
    import App from './App';
    import {name as appName} from './app.json';

    AppRegistry.registerComponent(appName, () => App);

Ändern zu:

    import App from './src/App';

von nun an wir die App.js aus src geladen.

Custom component

neue Datei anlegen

Custom.tsx

import React from 'react'
import { Text, StyleSheet } from 'react-native'

export const CustomHeader = () => {
    return (
        <Text style={styles.red}>Hallo</Text>
    )
}

const styles = StyleSheet.create({
    red: { color: "red" }
})

Custom in App bekannt machen:

App.js

import { CustomHeader } from './Custom'
...
<SafeAreaView>
    <ScrollView
        <CustomHeader />
        ...

Image resources

https://reactnative.dev/docs/images

Aus den quellen geht hervor, dass pfade für images nicht dynamisch erstellt werden sollen, damit der builder echte referezen erzeugen kann.

also muss man alle varianten der bilder anderweitig erefernezieren. gut genug scheint dabei ein const zu sein, das alle bilder mit required beinhlatet.

    touch resources/img/images.js

    export const IMAGES = {
        "matches":[
            require("./matches0-180x180_90dpi.png"),
            require("./matches1-180x180_90dpi.png"),
            require("./matches2-180x180_90dpi.png"),
            require("./matches3-180x180_90dpi.png"),
            require("./matches4-180x180_90dpi.png"),
            require("./matches5b-180x180_90dpi.png"),
            require("./matches6-180x180_90dpi.png"),
            require("./matches7-180x180_90dpi.png"),
            require("./matches8-180x180_90dpi.png"),
            require("./matches9-180x180_90dpi.png"),
            require("./matches10-180x180_90dpi.png")
        ],
        "matches2": {
            "first": require("./matches0-180x180_90dpi.png")
        }
    }

das ergebnis lässt sich dann einfach wie üblich integrieren:

import { IMAGES } from '../resources/img/images.js'

und einsetzen

import { Image } from 'react-native'
...
<Image source={IMAGES.matches[1]} />

Navigation

next step: navigation

https://reactnative.dev/docs/navigation

in vscode terminal öffnen:

npm install @react-navigation/native @react-navigation/stack
npm install react-native-reanimated react-native-gesture-handler react-native-screens \
    react-native-safe-area-context @react-native-community/masked-view

WICHTIG für iOS. Voraussetzung ist aber, dass https://cocoapods.org/ installiser ist. Dafür ist aber wiedrrum gem notwendig. was für ein scheiß.

also zuerst terminal öffnen:

sudo gem install cocoapods

Danach:

cd ios
pod install
cd ..

sind die nötigen binaries installiert, kann man mit dem coding anfangen:

! Wichtig ist, dass diese zeile die erste in der App.js ist:

import 'react-native-gesture-handler'

! Es kann sein, dass der bereits gestarttete simulator einen Fehler wirft.

Damit kann ein Stack und eine Navigation aufgebaut werden:

import { NavigationContainer } from '@react-navigation/native'
import { createStackNavigator } from '@react-navigation/stack'

Eine neue Komponete für den welcome screen, z.b. hier in der App.js

        ...
        function HomeScreen({ navigation }) {
            return (
                <View style=\{\{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                    <Button title="Show About"
                        onPress={() =>
                            navigation.navigate('About', { name: 'Hi' })
                        }
                    />
                </View>
            )
        }

        ...
        function AboutScreen({ navigation }) {
            return (
                <View style=\{\{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                    <Text>About Screen</Text>
                    <Button title="Back"
                        onPress={() =>
                            navigation.navigate('Home')
                        }
                    />
                </View>
            )
        }

Der Stack managed die gegebenen Screens:

const Stack = createStackNavigator();

Die neue App besitzt nur den zeiger auf den stack und lädt den HomeScreen:

    function App() {
        return (
            <NavigationContainer>
                <Stack.Navigator>
                    <Stack.Screen name="Home" component={HomeScreen} />
                    <Stack.Screen name="About" component={AboutScreen} />
                </Stack.Navigator>
            </NavigationContainer>
        )
    }

Alles schön und gut, aber wenn ein problem auftaucht, wie folgendes ists nervig. ofenbar ist das ganze gebilde doch nicht so stabil wie gedacht:

https://github.com/software-mansion/react-native-gesture-handler/issues/676

RNGestureHandlerModule.default.Direction Fehler

Hier soll wieder ein pod install helfen:

cd ios
pod install

nach dem restart des server und des rerun des ios builds, klappt die kiste.

Läuft

Tritt ein fehler, wie, fehlt dem system ein navigation parameter:

ReferenceError: Can't find variable: navigation

Button.props.onPress
    App.js:68:24

Navigation fehlt-Fehler

in meinem fall ist das der Button AboutScreen, der zurück zum HomeScreen führt. Hier fehlte navigation im AboutScreen:

function AboutScreen({ navigation }) {

Nach der änderung läuft die app "instant" im simulator. Das ist echt klasse.

Installation auf Devices

ios

https://reactnative.dev/docs/running-on-device.html

um das programm auf den devices zu installieren, also ohne server auf dem entwickler rechner, ist es nötig xcode aufzurufen, den build für das gewänschte device zu starten und voila! ferig.

cd ios
Doppelklick auf AwesomeProject.xworkspace

Der Ladevorgang kann eine Weile dauern, immerhin müssen viele Dateien indiziert werden.

Fehler beim Build:

fatal error: module map file '/Users/damian/Library/Developer/Xcode/DerivedData/AwesomeProject-bswttjrrzynioteopnzwdrgtimtj/Build/Products/Debug-iphoneos/YogaKit/YogaKit.modulemap' not found

Das komt davon, wenn man nicht die AwesomeProject.xworkspace sondern die AwesomeProject.xproject startet. RTFM!

Flipper Debugger

https://fbflipper.com/

Lessons Learned

  • React Native macht echt spaß, Typescript sei dank.
  • Sowohl iOS als auch Android sind im Minimla-Setup flüssig nutzbar.
  • Typescript!