Verwenden von React-Navigation 3.0 in React Native-Apps

React-Navigation ist wahrscheinlich die einzige Abhängigkeit, die ich in React Native-Apps verwende. Bisher bin ich damit zufrieden, dann kam Version 3.0 mit ein paar bahnbrechenden Änderungen heraus. Es ist keine so große Sache, aber es kann uns irgendwann zu einem Upgrade führen, wenn wir nicht genug Aufmerksamkeit schenken. Hier ist meine Erkundung und wie man die Upgrade-Probleme überwindet.

Was mir an React-Navigation gefällt, ist die gründliche Dokumentation, die einfach anpassbaren APIs und die sehr raffinierte Verwendung. Es löst fast alle Grundbedürfnisse.

Reaktionsnavigation

Ich lese gerne Quellcode und war überrascht zu sehen, dass React-Navigation reiner Javascript-Code ist.

module.exports = {
  // Native
  get createAppContainer() {
    return require('[@react](http://twitter.com/react)-navigation/native').createAppContainer;
  },
  get createNavigationContainer() {
    console.warn(
      '`createNavigationContainer()` has been deprecated, please use `createAppContainer()` instead. You can also import createAppContainer directly from [@react](http://twitter.com/react)-navigation/native'
    );
    return require('[@react](http://twitter.com/react)-navigation/native').createAppContainer;
  },
  get createKeyboardAwareNavigator() {
    return require('[@react](http://twitter.com/react)-navigation/native').createKeyboardAwareNavigator;
  },
}

„react-navigation/native“ bezieht sich auf dieses getrennte „react-navigation-native“, und es stützt sich wiederum auf „react-navigation-core“, und sie alle sind Javascript-Code. Ich dachte, es ist nur ein Javascript-Wrapper um Activity oder UINavigationViewController, aber das sind sie nicht. Wie hübsch ist das. Der gesamte Code ist einen Blick wert.

Auch alle Tab- und Stack-Navigatoren wie React-Navigation-Tabs und React-Navigation-Stack wurden aus Gründen der Modularität in getrennte Repos verschoben. Der Router- und Ereignismechanismus scheint vom Reaktionskontext in NavigationContext angetrieben zu werden

import createReactContext from 'create-react-context'; 
const NavigationContext = createReactContext(undefined); 
export default NavigationContext;

Upgrade auf 3.0

Der Migrationsleitfaden zu 3.0 ist recht einfach, aber es gibt einige Fallstricke, auf die wir achten müssen. Vor dem Upgrade verwendete ich React-Native 0.57.5 und React-Navigation 2.0

Installieren Sie zunächst Version 3.0 zusammen mit React-Native-Gesture-Handler

npm install react-navigation@^3.0.0
npm install react-native-gesture-handler

Wie brentvatne betonte, werden @react-navigation/core und @react-navigation/native vonreakt-navigation installiert. Version 3.0 ist auch das erste Mal, dass die React-Navigation von einem nativen Modul außerhalb des React Native Core abhängt.

React-Native-Gesture-Handler ist ein Satz von deklarativen APIs, die das plattformnative Berührungs- und Gestensystem für React Native verfügbar machen. Mehr darüber, wie es in der Reaktionsnavigation verwendet wird, können Sie im Vortrag Alles beginnt mit der Navigation

sehen

Die Eigenschaft „State“ von undefined kann in iOS nicht gelesen werden

React-native-gesture-handler hat etwas Objective C, das native APIs sind. Dieses Problem liegt daran, dass die Bibliothek nicht mit unserem Xcode-Projekt verknüpft ist. Ich habe oft Probleme mit React-Native Link und CocoaPods, daher ziehe ich normalerweise Drag RNGestureHandler.xcodeproj in Xcode. Das finden Sie in ../node_modules/react-native-gesture-handler/ios/RNGestureHandler.xcodeproj

Denken Sie dann in Link Binary with Libraries daran, libRNGestureHandler.a

auszuwählen

(0 , _reactNavigation.default) ist keine Funktion

Im Abschnitt Expliziter App-Container erforderlich für den Stammnavigator heißt es:„In der Vergangenheit konnte jeder Navigator als Navigationscontainer auf der obersten Ebene Ihrer App fungieren, weil sie alle in „Navigationscontainer“ eingeschlossen waren. Der Navigationscontainer, jetzt als App-Container bekannt, ist eine Komponente höherer Ordnung, die den Navigationsstatus Ihrer App verwaltet und die Interaktion mit der Außenwelt handhabt, um Verknüpfungsereignisse in Navigationsaktionen umzuwandeln und so weiter.“.

Jetzt ist ein expliziter Anwendungscontainer erforderlich. Das Problem taucht auf, wenn wir so deklarieren

import createAppContainer from 'react-navigation'

Wenn Sie sich den Beispielcode genauer ansehen, sieht es aus wie

import {
  createStackNavigator,
  createAppContainer
} from 'react-navigation';
const MainNavigator = createStackNavigator({...});
const App = createAppContainer(MainNavigator);

Wenn Sie sich den Code ansehen, wie die Top-Eigenschaften der Reaktionsnavigation exportiert werden, ist klar, dass createAppContainer kein Standardexport ist, also müssen wir geschweifte Klammern verwenden.

module.exports = {
  // Native
  get createAppContainer() {
    return require('[@react](http://twitter.com/react)-navigation/native').createAppContainer;
  },
}

Und der Quellcode für createAppContainer befindet sich im Inneren von „react-navigation-native“ bietet zusätzliche Informationen für neugierige Leser.

/**
 * Create an HOC that injects the navigation and manages the navigation state
 * in case it's not passed from above.
 * This allows to use e.g. the StackNavigator and TabNavigator as root-level
 * components.
 */
export default function createNavigationContainer(Component) {
  class NavigationContainer extends React.Component {
    subs = null;

_renderLoading() {
      return this.props.renderLoadingExperimental
        ? this.props.renderLoadingExperimental()
        : null;
    }
}

Jetzt können wir React-Navigation 3.0 wie unten verwenden. Normalerweise trenne ich Navigatoren, also habe ich RootNavigator, der für die Einrichtung des Root-Bildschirms verantwortlich ist.

// [@flow](http://twitter.com/flow)

import React from 'react'
import createAppContainer from 'react-navigation'
import makeRootNavigator from './src/screens/root/RootNavigator'

const RootNavigator = makeRootNavigator({})
const AppContainer = createAppContainer(RootNavigator)

type Props = {}

export default class App extends React.Component<Props> {
  render() {
    return <AppContainer />
  }
}

undefined ist kein Objekt, das „RNGestureHandlerModule.State“ in Android auswertet

Jetzt bekommen wir dieses Problem erneut, aber auf Android. Ich vertraue React-Native Link nicht, also verlinke ich die Bibliothek manuell.

Gehen Sie zu app build.gradle, suchen Sie nach dem Abhängigkeitsblock und deklarieren Sie

implementation project(':react-native-gesture-handler')

Fügen Sie außerdem in settings.gradle

hinzu
include ':react-native-gesture-handler'
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android')

Importieren Sie dann in MainApplication.java die Bibliothek und deklarieren Sie das React Native-Paket

import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;

[@Override](http://twitter.com/Override)
protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
        new MainReactPackage(),
        new RNGestureHandlerPackage(),
    )
}

Die React-native-gesture-handler-Dokumentation erwähnt etwas wie createReactActivityDelegate, aber ich sehe nicht, dass es notwendig ist.

[@Override](http://twitter.com/Override)
protected ReactActivityDelegate createReactActivityDelegate() {
  return new ReactActivityDelegate(this, getMainComponentName()) {
    [@Override](http://twitter.com/Override)
    protected ReactRootView createRootView() {
     return new RNGestureHandlerEnabledRootView(MainActivity.this);
    }
  }
}

Gradle löschen und nativen Cache reagieren

Der Cache kann uns manchmal verwirren, daher ist es am besten, den Cache während dieser Aktualisierungsphase zu leeren, um sicherzustellen, dass wir neu beginnen.

Wir können Gradle löschen, indem wir explizit Caches entfernen

rm -rf $HOME/.gradle/caches/

oder mit gradlew

./gradlew cleanBuildCache

Außerdem sollten wir den nativen Reaktionscache für das aktuelle Projekt ungültig machen

npm start -- --reset-cache

Danke fürs Lesen. Mögest du den Code weiter kompilieren.

Ursprünglicher Beitrag https://codeburst.io/using-react-navigation-3-0-in-react-native-apps-38cd5020fbbe