React Native Ökosystem (Ende 2016, Anfang 2017)

Im September 2016 kam bei meinen Arbeitgeber die Frage auf, mit welchen Mitteln würde man die nächste App angehen. Produktiv haben wir erfolgreich eine Ember-basierende App und eine Meteor-basierende App. Was sagen andere die Erfahrungen mit den Techs gemacht haben, würden die dieses wieder verwenden? Wie bekommt man das “Native App Erlebnis” aka 60fps hin?

In einen ersten Schritt habe ich auf den einschlägigen Kanälen nach Expertenmeinungen gesucht und zusammengetragen im Dokument “Stand der Web Apps: Native vs. Hybrid vs. Mobile” (PDF).

Daraus kristalisierte sich, dass React Native ein zwar junges aber doch schon dank massivem Support durch Facebook gereiftes Projekt ist. Um mittelfristig eine fundierte Entscheidung treffen zu können, war eine Analyse der Möglichkeiten des Ökosystems unausweichlich.

Die beste Erfahrung macht man indem man eine App wirklich programmiert. Ich kann ein Buch zu NodeJS lesen, aber wenn ich die ersten Zeilen programmiere, dann bekommt man erst mit, was es heißt in der Callback-Hölle zu landen. Da kamen mir Pilzdaten meines Vaters ganz gelegen. Listendarstellung, Detailansicht, Bilder, Merkliste, Datenhaltung mit Redux - wird alles benötigt, ist dann eine echte App. Anhand dieses mittelkleinen Projektes habe ich mich dann durch die verschiedenen Facetten gehangelt und recherchiert.

Am Ende entstand ein Vortrag, den ich im November/Dezember bei meinen Arbeitgeber und auch im Januar bei DresdenJS gehalten habe - in verschiedenen Kontexten natürlich. Zudem ist mittlerweile für CodeforChemnitz der Theaterwecker als App in der Entwicklung.

Folien zum Vortrag “Native App Entwicklung auf Pilzen” - in drei Teilen:

Projekte:

Nachfolgend sind noch die ganzen Recherchen gelistet - hauptsächlich auch für mich selbst zum nachschauen.

Einstieg, Kernidee, Dokumentation, Quellen

  • Use JavaScript as the language doesn’t have a long compilation cycle time.
  • Implement a tool called Packager that transforms es6/flow/jsx files into normal JavaScript that the VM can understand. It was designed as a server that keeps intermediate state in memory to enable fast incremental changes and uses multiple cores.
  • Build a feature called Live Reload that reloads the app on save.

React und seine Alternativen

Die Besonderheit liegt darin, mittels der Komponenten HTML in JavaScript integrieren zu wollen, statt andersherum. Das kommt einerseits der Übersichtlichkeit des Codes zugute und andererseits lassen sich dadurch von Hand durchgeführte DOM-Manipulationen vermeiden, an denen bspw. Web Components und AngularJS weiterhin kranken (etwa im Fall von Data Binding).

(Quelle)

UIExplorer (per Playstore verfügbar!)

Getting Started

  • Follow the Getting Started guide to install React Native and its dependencies.
  • Check out this tutorial to walk through your first project that fetches real data and displays it in a list.
  • Open the UIExplorer example project to see a list of components that ship with React Native.
  • Install the React Developer Tools for Chrome or Firefox for better debugging (read more).
  • Try out apps from the Showcase to see what React Native is capable of!

React Native TODO Example

rnpm - React Native Package Manager (deprecated) braucht man nicht mehr, wurde in React Native Core übernommen

Props vs. State - Component API

  • Doku: http://www.reactnativeexpress.com/component_api
  • props sind schreibgeschützt und nicht für den momentanen änderbaren Zustand einer Komponente geeignet
  • state niemals direkt ändern mit this.state.bla=2 sondern immer über this.setState - damit rendering angestoßen wird

this.props

Components can be configured upon instantiation by passing properties to the constructor - these properties are called props. props may be accessed from within the component’s methods as this.props, in order to alter how the component is rendered and/or how it behaves. However, props must not be altered from within the component’s methods. A parent element may alter a child element’s props at any time. The child element will generally re-render itself to reflect its new configuration parameters. A child component may decide not to re-render itself even though its configuration has changed, as determined by shouldComponentUpdate() (more on this in the Component Lifecycle API section).

this.state

Components may maintain their state internally within the object state. this.state may be accessed from within component methods. Unlike props, parent elements may not access a child’s state, as it is intended to manage the child’s internal state rather than external configuration. Note that you should never directly assign to a specific key within the state object, e.g. this.state.foo = ‘bar’, but instead use the method this.setState().

Lifecycle API

http://www.reactnativeexpress.com/lifecycle_api

Components have a lifecycle: they are instantiated, mounted, rendered, and eventually updated, unmounted, and destroyed. The lifecycle helps manage the complexity of different platform APIs (iOS, Android) by providing a simple, consistent abstraction layer. The lifecycle also allows you to optionally execute custom code at each step for more fine-grained control of the rendering.

Bei JS-Fehler in iOS App kann per “JS Reload” im Fuss das JS neu geladen werden - ohne Rebuild

state in constructor setzen vs. getInitialState

Ask: What is the difference between using constructor vs getInitialState in React / React Native?

this.state in constructor direkt bei ES6 Klassen, getIintialState bei ES5

Debugging

Debugging aktivieren

  • Doku
  • auf iOS -> Cmd+D
  • auf Android -> Cmd+M

Reactotron

A desktop app for inspecting your React JS and React Native projects.

react-native-debugger

The standalone app based on official debugger of React Native, and includes React Inspector / Redux DevTools

Stetho

Stetho is a debug bridge for Android applications, enabling the powerful Chrome Developer Tools and much more.

Upgrade RN (via Git)

Doku

react-native-git-upgrade

benutzt Breaking Changes aus Wiki https://github.com/facebook/react-native/wiki/Breaking-Changes

Redux

Tutorial

Reducer sind Pure Funktionen, dürfen übergebenen state nicht ändern, sondern ein neues Object this.state + setState an React Komponenten kann komplett entfernt werden, da Zustand von Redux über Props eingespült wird Eventhandler kommen auch per Props rein, z.B. onRemoveSmth

Prior Art: basiert auf Flux (Facebooks State für React), Elm (“model view update” Architektur), Immutable (persistene Datenstruktur, Undo History!)), Baobab, Rx (u.a. Observables)

Komponenten an Redux anbinden

combineReducers und loadStore mit preloadedState

Memoized Selectors um mapStateToProps bei großen Datenmengen nur mit den Änderungen zu bedienen

Realm mit Redux Beispiel

Finite State Machine in Redux

Undo History

Production Build Android

Signaturfile erzeugen:

keytool -genkey -v -keystore my-keystore.keystore -alias name_alias -keyalg RSA -validity 10000

Android Build:

./gradlew assembleRelease
jarsigner -verbose -keystore my-keystore.keystore app/build/outputs/apk/app-release-unsigned.apk name_alias
adb install app/build/outputs/apk/app-release-unsigned.apk

Build beschleunigen -> Gradle Daemon aktivieren in ./android/gradle.properties -> org.gradle.daemon=true

Android Emulator (AVD) von Kommandozeile starten

/usr/local/bin$ ln -s $ANDROID_HOME/tools/emulator
emulator -list-avds 
emulator -avd Nexus_5_API_23_x86

Fehler “Qt library not found at /usr/local/bin/lib64/qt/lib”? Antwort auf SO

brew install qemu

es bleiben Fehler :(

brew remove qemu

/usr/local/bin$ ln -s $ANDROID_HOME/tools/android 
android avd

:)

ListView Performance

Lazy Load

  • Große Datenmengen führen im verwendeten RN-Componentes List und ListView zu langen Ladezeiten
  • Lazyload baut Views und Inhalte bei Bedarf aus State-Daten
  • [react-native-lazyload](https://www.npmjs.com/package/react-native-lazyload()
  • Commit in pilzliste-react-native-redux

Offizielle Performance-Hinweise

Layout

Image

Fehler “The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.”

Pilzbilder kleinrechnen

  • CLI options für IM resize
  • xargs
  • in httpdocs/original:
    find . -type f -name "*.jpg"  -print0 | xargs -0 -I {} -P 4 convert {} -thumbnail "60x60" -strip  ../thumbnails/{}.png 
    

Blog-Posts:

Ein neuer Router ist aktuell auf der Roadmap als Alternative zu Navigator, NavigationExperimental, und ExNavigation.

TouchableHighlight

Tap auf ein Element, highlightet es und führt eine Aktion durch. (Doku)

View display:none, visbility:hidden? height:0 / destroy Issue

Iteration über Elemente mit Child components

benötigt immer key als Attribut

{ this.state.items.map((item, i) => ( 
          <ListeItem key={i} item={item} /> 
        )) }

Fuzzy-Suche

Debounce TextInput

Images mit Ladebalken

Images cachen

Offline first

App Intro (erste Bedienhilfe)

react-native-app-intro

Popups, Dialoge

react-native-popup-dialog

React Parts

RN Plattformen

Android, iOS

macOS Desktop Apps react-native-macos

Windows UWP (Universal Windows Platform) react-native-windows (aktiver als MacOS!)

Web react-native-web (Grundlage für App-Demos in offizieller Doku)
Starter

Stylesheets

react-with-styles und react-with-styles-interface-react-native

Libs

Design Pakete

Organisation

How to better organize your React applications

Storybook

Bootstrapping UI: Storybook react-storybook getstorybook.io