React Native: Info-Screen implementieren



Was bisher geschah?

In der zuvor hier zum Projekt hinzugefügten Datei src/screens/About.tsx wird die App-Informationsseite erstellt.

Infoseite implementieren

Die src/screens/About.tsx-Datei wie folgend modifizieren.

src/screens/About.tsx

import React from 'react';
import {
  Container, Content, Form, Text, View, Item, Thumbnail
} from 'native-base';
import { Col, Row, Grid } from 'react-native-easy-grid';
import { useTranslation } from 'react-i18next';
import { StyleSheet, Linking } from 'react-native';
import Header from '../components/Header';
import { DefaultScreenProps } from '../types/default';

/**
 * get app name and version from JSON
 */
const appinfo = require('../../app.json');
const appicon = require('../../android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png');

const About = (props: DefaultScreenProps): React.FunctionComponentElement<DefaultScreenProps> => {
  const { t, i18n } = useTranslation();

  return (
      <Container>
        <Header navigation={props.navigation} title={t('about.headerTitle')} />
        <View> 
        <Item fixedLabel>
          <Grid style={styles.grid}>
            <Row style={styles.gridRow}>
              <Col style={styles.gridColumnThumbnail}>
                <Thumbnail square large style={styles.thumbnail} source={appicon}></Thumbnail>
              </Col>
              <Col style={styles.gridColumnVersion}>
                <Text style={styles.appname}>{appinfo.displayName}</Text>
                <Text style={styles.appversion}>Version {appinfo.versionName}</Text>
                <Text style={styles.hyperlink} onPress={() => Linking.openURL('http://www.technik-tipps-und-tricks.de')}>Technik Tipps und Tricks</Text>
              </Col>
            </Row>
          </Grid>
        </Item>
      </View>
        <Content>
        <View style={styles.descriptionView}>
          <Text>
            <Text style={styles.descriptionAppName}>{appinfo.displayName}</Text>
            <Text style={styles.descriptionText}> {t('about.description')}</Text>
          </Text>
        </View>
        <View style={styles.hyperlinkView}>
          <Text>{t('about.website')}: <Text style={styles.hyperlink} onPress={() => Linking.openURL('http://www.technik-tipps-und-tricks.de/programmierung/javascript/react-native/')}>React Native Tutorial</Text></Text>
        </View>
        </Content>
      </Container>
  );
};

const styles = StyleSheet.create({
  appname: {
    fontSize: 20,
    fontWeight: "bold" 
  },
  appversion: {
    fontSize: 16
  },
  grid: {
    width: 'auto', 
    height: 80, 
    margin: 10
  },
  gridRow: {
    height: 80
  },
  gridColumnThumbnail: {
    backgroundColor: 'white', 
    height: 80, 
    width: 80
  },
  thumbnail: {
    width: 80, 
    height: 80
  },
  gridColumnVersion: {
    backgroundColor: 'white', 
    height: 80, 
    paddingLeft: 10
  },
  descriptionView: {
    flex: 1, 
    flexDirection: 'row', 
    flexWrap: 'wrap', 
    padding: 20,
  },
  descriptionAppName: {
    fontStyle: 'italic', 
    fontWeight: 'bold', 
    flex: 1, 
    flexDirection: 'row', 
    flexWrap: 'wrap'
  },
  descriptionText: {
    flex: 2, 
      flexDirection: 'row', 
      flexWrap: 'wrap'
    },
  hyperlinkView: {
    alignItems: 'flex-start', 
    padding: 20, 
    paddingVertical: 5
  },
  hyperlink: {
    color: 'blue',
    textDecorationLine: 'underline',
    fontWeight: "bold"
  },
});

export default About;

JSON-Übersetzungsdateien aktualisieren

In den Sprachdateien den Bereich “about” ergänzen.

src/translations/en.json

"about": {
    "headerTitle": "About",
    "description": "is a mobile React Native componentens demo app.",
    "website": "Website"

  }

src/translations/de.json

"about": {
    "headerTitle": "Info",
    "description": "ist eine mobile React Native Komponenten-Demo-App.",
    "website": "Webseite"
  }

Der fertige About-Screen

001-ReactNativeDemo-About-Page [Image]

Wie geht es weiter?

War diese Seite für dich informativ? Hat sie dir gefallen und geholfen?

Dann unterstütze die Weiterentwicklung mit einer kleinen Spende!

Die Spenden werden für die Lizenzen sowie neue Hard- und Software verwendet, die für weitere Projekte auf dieser Webseite eingesetzt werden.





React Native: Screens und Navigation hinzufügen



Was bisher geschah?

Es wird eine Navigation und zusätzliche Bildschirmseiten mit den Einstellungen, der Hauptseite, Info und einem leeren Dummy-Screen erstellt. Die “Welcome to React“-Seite bleibt als Home-Screen bestehen. In dem Header wird links eine Menü- und rechts eine Einstellungen-Schaltfläche eingefügt, die jeweils eine Seitenleiste mit Auswahl-Optionen einblenden. In der Mitte soll der Titel der aktiven Seite angezeigt werden.

Screen Properties Objekt-Typ

Die src/types/default.ts-Datei wird mit  dem  DefaultScreenProps-Typ erweitert. Der Typ erbt von DefaultProps und enthält die Navigations-Parameter für die einzelnen Seiten.

src/types/default.ts

import React from 'react';
import { NavigationParams, NavigationScreenProp, NavigationState } from 'react-navigation';

export interface DefaultProps {
  children?: React.ReactNode;
}

export interface DefaultScreenProps extends DefaultProps{
  navigation: NavigationScreenProp<NavigationState, NavigationParams>;
}

Screen-Header erstellen

Der Screen-Header enthält den Titel der aktiven Seite und die Menü- und Einstellungen-Schaltflächen.

Einen neuen Ordner src/components mit der Datei Header.tsx erstellen.

src/components/Header.tsx

import React from 'react';
import {
  Body, Button, Header as NativeHeader, Icon, Left, Right, Text, Title,
} from 'native-base';
import { StyleSheet, Alert } from 'react-native';
import { DefaultScreenProps } from '../types/default';
import { DrawerActions } from 'react-navigation-drawer';

interface HeaderProps extends DefaultScreenProps{
  title: string;
}

const Header = (props: HeaderProps): React.FunctionComponentElement<HeaderProps> => {

  const onClickMenuButton = (): void => {
    props.navigation.navigate({routeName: 'Menu', action: DrawerActions.toggleDrawer()});
  };

  const onClickMoreButton = (): void => {
    props.navigation.navigate({routeName: 'More', action: DrawerActions.toggleDrawer()});
  };

  return (
    <NativeHeader>
      <Left style={styles.iconWrapper}>
        <Button transparent onPress={onClickMenuButton}>
          <Icon name="menu" />
        </Button>
      </Left>
      <Body>
        <Title>
          <Text style={styles.headerText}>{props.title}</Text>
        </Title>
      </Body>
      <Right style={styles.iconWrapper}>
        <Button transparent onPress={onClickMoreButton}>
          <Icon name="more" />
        </Button>
      </Right>
    </NativeHeader>
  );
};

const styles = StyleSheet.create({
  iconWrapper: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  headerText: {
    fontSize: 22,
    fontWeight: 'bold',
    textAlign: 'center',
    color: 'white',
    width: 200,
    flexDirection: 'row',
    flexWrap: 'nowrap'
  }
});

export default Header;

Eingesetzt wird hier die Header-Komponente aus dem NativeBase-Paket. Sie hat drei Bereiche. Links(<Left />) für die Menü-Schaltfläche, Mitte (<Body />) für den Titel und rechts (<Right />) für die Einstellungen-Schaltfläche. Der Titel wird aus den JSON-Übersetzungsdateien geholt. Die Schaltflächen lösen Ereignisse aus, die links bzw. rechts eine Sidebar mit den Auswahl-Optionen einblenden.


Screens erstellen

Es werden vier Screens erstellt. Home für die “Welcome to React”-Seite, Settings für die Einstellungen, About für die App-Informationen und Dummy als Vorlage für die weitere Screen-Implementierungen.

Zuerst einen neuen Ordner src/screens mit vier Dateien: Home.tsx, Settings.tsx, About.tsx und Dummy.tsx erstellen.

Home

Diese Seite enthält eine modifizierte Kopie der “Welcome to React” – Hauptseite aus App.tsx.

src/screens/Home.tsx

import React from 'react';
import { StyleSheet } from 'react-native';
import { Container, Content, Form, Label } from 'native-base';
import { useTranslation } from 'react-i18next';
import Header from '../components/Header';
import {
  Header as ReactHeader,
  LearnMoreLinks,
  Colors,
  DebugInstructions,
  ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
import { DefaultScreenProps } from '../types/default';

console.disableYellowBox = true;

const Home = (props: DefaultScreenProps): React.FunctionComponentElement<DefaultScreenProps> =>{ 
  const { t, i18n } = useTranslation(); 

  return (
    <Container>
      <Header navigation={props.navigation} title={t('home.headerTitle')} />
      <Content>
        <ReactHeader />
        <Form style={styles.body}>
          <Label style={styles.sectionContainer}>
            <Label style={styles.sectionTitle}>Step One</Label>
            <Label style={styles.sectionDescription}>
              Edit <Label style={styles.highlight}>App.tsx</Label> to change
              this screen and then come back to see your edits.
            </Label>
          </Label>
          <Form style={styles.sectionContainer}>
            <Label style={styles.sectionTitle}>See Your Changes</Label>
            <Label style={styles.sectionDescription}>
              <ReloadInstructions />
            </Label>
          </Form>
          <Form style={styles.sectionContainer}>
            <Label style={styles.sectionTitle}>Debug</Label>
            <Label style={styles.sectionDescription}>
              <DebugInstructions />
            </Label>
          </Form>
          <Form style={styles.sectionContainer}>
            <Label style={styles.sectionTitle}>Learn More</Label>
            <Label style={styles.sectionDescription}>
              Read the docs to discover what to do next:
            </Label>
          </Form>
          <LearnMoreLinks />
        </Form>
      </Content>
    </Container>
  );
};

const styles = StyleSheet.create({
  body: {
    backgroundColor: Colors.white,
  },
  sectionContainer: {
    marginTop: 32,
    paddingHorizontal: 24,
  },
  sectionTitle: {
    fontSize: 24,
    fontWeight: '600',
    color: Colors.black,
  },
  sectionDescription: {
    marginTop: 8,
    fontSize: 18,
    fontWeight: '400',
    color: Colors.dark,
  },
  highlight: {
    fontWeight: '700',
  },
});

export default Home;

Settings

Das Einstellungen-Bildschirm enthält eine Auswahl der Sprache und die Passworteingabe.

src/screens/Settings.tsx

import React from 'react';
import {
  Button, Container, Content, Form, Text, Item, Picker, Icon, Label, Input,
} from 'native-base';
import { useTranslation } from 'react-i18next';
import { StyleSheet, Alert } from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import Header from '../components/Header';
import { DefaultScreenProps } from '../types/default';
import { AppState } from '../reducers/appReducer';
import { setSelectedLanguage, SetPassword } from '../actions/appActions';

const Settings = (props: DefaultScreenProps): React.FunctionComponentElement<DefaultScreenProps> => {
  const { t, i18n } = useTranslation();
  const dispatch = useDispatch();
  const selectedLanguage = useSelector((state: { app: AppState}) => state.app.selectedLanguage);
  const password = useSelector((state: { app: AppState}) => state.app.password);

  const onChangePassword = (newPassword: string): void => {
    dispatch(SetPassword(newPassword));
  };

  const savePassword = () => {
    Alert.alert(t('settings.savePassword'));
  };

  const onSelectedLanguageChange = (newSelectedLanguage: string): void => {
    i18n.changeLanguage(newSelectedLanguage).then((value) => {
      dispatch(setSelectedLanguage(newSelectedLanguage));
    });
  };

  return (
      <Container>
        <Header navigation={props.navigation} title={t('settings.headerTitle')} />
        <Content>
          <Form>
            <Item picker style={styles.settingsPickerItem}>
              <Label>
                {t('settings.language')}:{' '}
              </Label>
              <Picker
                mode="dropdown"
                iosIcon={<Icon name="arrow-down" />}
                style={{ width: undefined }}
                iosHeader={t('settings.selectLanguage')}
                placeholder={t('settings.selectLanguage')}
                placeholderStyle={{ color: '#bfc6ea' }}
                placeholderIconColor="#007aff"
                selectedValue={selectedLanguage}
                onValueChange={onSelectedLanguageChange}
              >
                <Picker.Item label={t('settings.languages.german')} value="de" />
                <Picker.Item label={t('settings.languages.english')} value="en" />
              </Picker>
            </Item>
            <Item picker style={styles.settingsPickerItem}>
              <Label>
                {t('settings.password')}:{' '}
              </Label>
              <Input
                value={password}
                onChangeText={onChangePassword}
                secureTextEntry
                onEndEditing={savePassword}
              />
            </Item>
            <Button style={styles.saveButton}>
              <Text>{t('general.save')}</Text>
            </Button>
          </Form>
        </Content>
      </Container>
  );
};

const styles = StyleSheet.create({
  saveButton: {
    margin: 8,
    justifyContent: 'center',
  },
  settingsPickerItem: {
    marginLeft: 8,
  },
});

export default Settings;


Dummy

Dummy ist eine leere Vorlage für spätere Implementierungen. Sie enthält als Platzhalter nur einen Text und einen Link.

src/screens/Dummy.tsx

import React from 'react';
import {
  Container, Content, Form, Text,
} from 'native-base';
import { useTranslation } from 'react-i18next';
import { StyleSheet, Linking } from 'react-native';
import Header from '../components/Header';
import { DefaultScreenProps } from '../types/default';

const Dummy = (props: DefaultScreenProps): React.FunctionComponentElement<DefaultScreenProps> => {
  const { t, i18n } = useTranslation();

  return (
      <Container>
        <Header navigation={props.navigation} title={t('dummy.headerTitle')} />
        <Content>
          <Form>
            <Text style={styles.text}>{t('dummy.text')}</Text>
            <Text>Link: 
              <Text style={styles.link} 
                onPress={() => Linking.openURL('http://www.technik-tipps-und-tricks.de')}>
                Technik Tipps und Tricks
              </Text>
            </Text>
          </Form>
        </Content>
      </Container>
  );
};

const styles = StyleSheet.create({
  text: {
    color: 'red',
  },
  link: {
    color: "#1B95E0",
    textDecorationLine: "underline",
    fontWeight: "bold"
  },
});

export default Dummy;

About

Die Info-Seite wird später die App-Informationen anzeigen, wie die Version, den Anbieter, ein Icon usw.

src/screens/About.tsx

import React from 'react';
import {
  Container, Content, Form, Text,
} from 'native-base';
import { useTranslation } from 'react-i18next';
import { StyleSheet } from 'react-native';
import Header from '../components/Header';
import { DefaultScreenProps } from '../types/default';

const About = (props: DefaultScreenProps): React.FunctionComponentElement<DefaultScreenProps> => {
  const { t, i18n } = useTranslation();

  return (
      <Container>
        <Header navigation={props.navigation} title={t('about.headerTitle')} />
        <Content>
          <Form>
            <Text style={styles.text}>{t('about.text')}</Text>
          </Form>
        </Content>
      </Container>
  );
};

const styles = StyleSheet.create({
  text: {
    color: 'red',
  },
  link: {
    color: "#1B95E0",
    textDecorationLine: "underline",
    fontWeight: "bold"
  },
});

export default About;

Internationalisierung ergänzen

Die Internationalisierungsdateien mit der Übersetzung ergänzen.

src/translations/en.json

{
  "general": {
    "loading": "Load...",
    "save": "Save",
    "messages": {
      "someMessage": "Some Message"
    },
    "errors": {
      "unknown": "Unknown error occurred!"
    }
  },
  "profile": {
    "headerTitle": "Personal Data",
    "fields": {
      "firstName": "first name",
      "lastName": "family name",
      "phoneNumber": "phone number",
      "emailAddress": "email Address"
    }
  },
  "home": {
    "headerTitle": "Home"
  },
  "settings": {
    "headerTitle": "Settings",
    "selectLanguage": "Select the Language",
    "language": "Language",
    "languages": {
      "german": "German",
      "english": "English"
    },
    "password": "Password",
    "savePassword": "Password successfully changed"
  },
  "dummy": {
    "headerTitle": "Dummy",
    "text": "Empty Dummy Page."
  },
  "about": {
    "headerTitle": "About",
    "text": "Empty Info Page."
  }
}

src/translations/de.json

{
  "general": {
    "loading": "Laden...",
    "save": "Speichern",
    "messages": {
      "someMessage": "Irgendeine Nachricht"
    },
    "errors": {
      "unknown": "Unbekannter Fehler aufgetreten!"
    }
  },
  "profile": {
    "headerTitle": "Persönliche Daten",
    "fields": {
      "firstName": "Vorname",
      "lastName": "Familienname",
      "phoneNumber": "Telefonnummer",
      "emailAddress": "E-Mail-Adresse"
    }
  },
  "home": {
    "headerTitle": "Start"
  },
  "settings": {
    "headerTitle": "Einstellungen",
    "selectLanguage": "Wähle die Sprache",
    "language": "Sprache",
    "languages": {
      "german": "Deutsch",
      "english": "Englisch"
    },
    "password": "Passwort",
    "savePassword": "Passwort erfolgreich geändert"
  },
  "dummy": {
    "headerTitle": "Dummy",
    "text": "Leere Dummy Seite."
  },
  "about": {
    "headerTitle": "Info",
    "text": "Leere Info Seite."
  }
}


Die linke und rechte Optionsleiste mit den Einträgen sollen je nach Klick auf das Menü- oder Mehr-Icon im Header eingeblendet werden.

Eine neue Datei src/components/MenuSidebar.tsx erstellen.

src/components/MenuSidebar.tsx

import React from 'react';
import {
  Body, Container, Content, Icon, Left, ListItem, Right, Text,
} from 'native-base';
import { FlatList } from 'react-native';
import { useTranslation } from 'react-i18next';
import { DefaultScreenProps } from '../types/default';

const MenuSidebar = (props: DefaultScreenProps): React.FunctionComponentElement<DefaultScreenProps> => {
  const { navigation } = props;
  const { t } = useTranslation();

  const routes = [{
    route: 'Home',
    text: t('home.headerTitle'),
    icon: 'home',
    iconColor: 'red',
  }, {
    route: 'Dummy',
    text: t('dummy.headerTitle'),
    icon: 'account',
    iconColor: '#FF9501',
  }];

  return (
    <Container>
      <Content>
        <FlatList
          data={routes}
          keyExtractor={(item) => item.route}
          renderItem={({ item }): React.FunctionComponentElement<DefaultScreenProps> => (
            <ListItem
              icon
              key={item.route}
              onPress={(): void => {
                navigation.navigate(item.route);
                navigation.closeDrawer();
              }}
            >
              <Left>
                <Icon
                  active
                  name={item.icon}
                  type="MaterialCommunityIcons"
                />
              </Left>
              <Body>
                <Text>{item.text}</Text>
              </Body>
              <Right />
            </ListItem>
          )}
        />
      </Content>
    </Container>
  );
};

export default MenuSidebar;

More-Sidebar

Eine neue Datei src/components/MoreSidebar.tsx erstellen.

src/components/MoreSidebar.tsx

import React from 'react';
import {
  Body, Container, Content, Icon, Left, ListItem, Right, Text,
} from 'native-base';
import { FlatList } from 'react-native';
import { useTranslation } from 'react-i18next';
import { DefaultScreenProps } from '../types/default';

const MoreSidebar = (props: DefaultScreenProps): React.FunctionComponentElement<DefaultScreenProps> => {
  const { navigation } = props;
  const { t } = useTranslation();

  const routes = [{
    route: 'Settings',
    text: t('settings.headerTitle'),
    icon: 'settings',
    iconColor: '#FF9501',
  }, {
    route: 'About',
    text: t('about.headerTitle'),
    icon: 'information-outline',
    iconColor: '#FF9501',
  }];

  return (
    <Container>
      <Content>
        <FlatList
          data={routes}
          keyExtractor={(item) => item.route}
          renderItem={({ item }): React.FunctionComponentElement<DefaultScreenProps> => (
            <ListItem
              icon
              key={item.route}
              onPress={(): void => {
                navigation.navigate(item.route);
                navigation.closeDrawer();
              }}
            >
              <Left>
                <Icon
                  active
                  name={item.icon}
                  type="MaterialCommunityIcons"
                />
              </Left>
              <Body>
                <Text>{item.text}</Text>
              </Body>
              <Right />
            </ListItem>
          )}
        />
      </Content>
    </Container>
  );
};

export default MoreSidebar;


AppContainer (Router) erstellen

Der AppContainer oder Router kapselt die Seitennavigation. Je eine DrawerNavigator-Komponente für die linke und rechte Seitenleiste werden erstellt und in einem SwitchNavigator zusammengefasst. Aus diesem wird der AppContainer gebildet.

Zuerst wird das DrawerNavigator-Paket installiert:

$ npm install react-navigation-drawer

Die Datei src/AppContainer.tsx erstellen.

src/AppContainer.tsx

import React from 'react';
import { createAppContainer, createSwitchNavigator } from 'react-navigation';
import { createDrawerNavigator } from 'react-navigation-drawer';
import MenuSidebar from './components/MenuSidebar';
import MoreSidebar from './components/MoreSidebar';
import Home from './screens/Home';
import Dummy from './screens/Dummy';
import Settings from './screens/Settings';
import About from './screens/About';

const MoreNavigator = createDrawerNavigator(
  {
    Settings: { screen: Settings },
    About: { screen: About }
  }, 
  {
    contentComponent: (props) => <MoreSidebar {...props} />,
    drawerPosition: 'right',
    drawerType: 'slide',
  }
);

const MenuNavigator = createDrawerNavigator(
  {
    Home: { screen: Home },
    Dummy: { screen: Dummy },
  }, 
  {
    contentComponent: (props) => <MenuSidebar {...props} />,
    drawerPosition: 'left',
    drawerType: 'slide',
  }
);

const RootNavigator = createSwitchNavigator(
  {
    Menu: { screen: MenuNavigator },
    More: { screen: MoreNavigator },
  }
);

const Router = createAppContainer(RootNavigator);

export default Router;

Router einbinden

Die App-Hautdatei App.tsx mit folgendem Inhalt ersetzen.

App.tsx

import React from 'react';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import { Root } from 'native-base';
import configureStore from './src/configureStore';
import { DefaultProps } from './src/types/default';
import Router from './src/AppContainer';
import I18nGate from './src/i18nGate';

const { store, persistor } = configureStore();

const App = (): React.FunctionComponentElement<DefaultProps> => {

  return (
    <Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
        <I18nGate>
          <Root>
            <Router />
          </Root>
        </I18nGate>
      </PersistGate>
    </Provider>
  );
};

export default App;

Die Provider– und PersistGate-Komponenten stellen den permanenten Redux-Speicher zur Verfügung. I18Gate dient der Internationalisierung, Root ist der App-Hauptcontainer und Router die Navigation mit den Screens.

Die fertige Navigation

001-Navigation-Screens [Image]

002-Navigation-Screens [Image]

003-Navigation-Screens [Image]

004-Navigation-Screens [Image]
 

Wie geht es weiter?

 

War diese Seite für dich informativ? Hat sie dir gefallen und geholfen?

Dann unterstütze die Weiterentwicklung mit einer kleinen Spende!

Die Spenden werden für die Lizenzen sowie neue Hard- und Software verwendet, die für weitere Projekte auf dieser Webseite eingesetzt werden.





React Native – Apps für Android und iOS parallel entwickeln


React_Native_ic_launcher_round [Image]Im Jahr 2011 setzte Facebook in seinem Newsfeed zum ersten Mal das von dem Facebook-Softwareingenieur Jordan Walke entwickelte JavaScript-Webframework React ein. Ein Jahr später folgte Instagram. Mitte 2013 wurde das Framework als Open-Source-Projekt veröffentlicht und man hat begonnen an einer nativen Portierung für mobile Android– und iOS-Geräte zu arbeiten. Die erste React Native Version wurde 2015 geboren. Die Bibliothek basiert auf React, nutzt aber kein Virtual DOM zum Rendern der UI-Komponente, sondern manipuliert über die JavaScript Bridge den nativen, plattformspezifischen Code. Java für Android und Objective-C für iOS. Daher werden für jede der beiden Plattformen ihre Entwicklungswerkzeuge aus Android Studio bzw. Xcode und CocoaPods für iOS benötigt.

Diese Entwicklung brachte viele Vorteile für Unternehmen, wie auch einzelne Entwickler. Nur ein einziges Projekt muss gepflegt werden um beide Plattformen zu unterstützen und die Entwickler brauchen nicht unbedingt die Java, Objective-C oder Swift Kenntnisse. Auch Webdesigner und Web-Developer können sich schnell in die Programmierung einarbeiten, da der Code auf den aus der Webentwicklung bekannten Sprachen wie JavaScript, HTML, CSS und JSON für Frontend und PHP oder Python für Backend basiert. Die Entwicklungskosten und der Zeitaufwand werden dadurch enorm reduziert.

React Native: Projektvorlage (Template) erstellen




Nach der Projektvorbereitung und Einrichtung der wichtigen Komponente, bevor man anfängt mit der eigentlichen Programmierung, kann man daraus ein Template für zukünftige Projekte erstellen. Wird ein Projekt mit so einer eingerichteten Vorlage initialisiert, sparrt man sich die Zeit für manuelles Einfügen und Einrichten der Erweiterungen.

Leeres Projekt erstellen

Siehe: Projekt anlegen und Projekt einrichten.

Projekt in ein Template umwandeln

Die Umwandlung eines Projektes in ein Template erfordert folgende Schritte:

  1. Template-Verzeichnis erstellen (path/template-name/template).
  2. Ordner und Dateien kopieren (ausser Build- und node_modules-Ordner)
  3. Gepunktete .-Dateien umbenennen
  4. Zusätzliche Template-Dateien hinzufügen (template.config.js, package.json, package-lock.json, .gitignore).

Hier ein Bash-Skript, das diese Arbeit automatisch erledigt (Download):

create-react-native-template.sh

#!/bin/bash

# IMPORTANT! Customize values for Paths, Files, Folders and further variables below!
# 1. Make script executable: chmod +x create-react-native-template.sh
# 2. Customize script.
# 3. Run script: ./create-react-native-template.sh
# 4. Create new React Native project from this template: npx react-native init --template file:///path/to/template/root/folder

# the template name
TEMPLATE_NAME="my-react-native-template-typescript"
# template version
TEMPLATE_VERSION="0.0.1"
# version of the package-lock.json file
LOCK_FILE_VERSION="1"
# author name
AUTHOR="Alexander Stepien"
# E-Mail address
AUTHOR_MAIL="alexwatermann@technik-tipps-und-tricks.de"
# homepage
HOMEPAGE="http://www.technik-tipps-und-tricks.de/it/programmierung/javascript/react-native"
# short template desription
DESCRIPTION="React Native template with TypeScript, Redux, Async-Storage, React-Navigation, NativeBase, i18next internalization."
# source project for template
PROJECT_PATH="/home/$USER/Development/REACT-NATIVE/ReactNativeDemo"
# absolute path to the template root folder
TEMPLATE_PATH="/home/$USER/Development/REACT-NATIVE/TEMPLATES/${TEMPLATE_NAME}"
# list of folders to be copied
FOLDER_LIST="
android 
ios 
src 
__tests__"
# list of files to be copied
FILE_LIST="
app.json 
App.tsx 
babel.config.js 
.buckconfig 
.eslintrc.js 
.gitattributes 
.gitignore 
index.js 
metro.config.js 
package.json 
.prettierrc.js 
tsconfig.json 
.watchmanconfig"


# copy project data to template
mkdir -p $TEMPLATE_PATH/template

if test -d $TEMPLATE_PATH/template; then
    echo "INFO: Ordner $TEMPLATE_PATH/template erstellt"
    
    # copy folders, exclude builds
    for FOLDERNAME in $FOLDER_LIST
    do
        if test -d $PROJECT_PATH/$FOLDERNAME; then
            if [ "$FOLDERNAME" == "android" ]; then
                rsync -a --exclude="app/build" --exclude=".directory" ${PROJECT_PATH}/android $TEMPLATE_PATH/template
            elif [ "$FOLDERNAME" == "ios" ]; then
                rsync -a --exclude="build" --exclude=".directory" ${PROJECT_PATH}/ios $TEMPLATE_PATH/template
            else
                cp -R $PROJECT_PATH/$FOLDERNAME $TEMPLATE_PATH/template
            fi
        else
            echo "WARNUNG: Ordner $FOLDERNAME nicht vorhanden."
        fi
    done
    
    # copy files
    for FILENAME in $FILE_LIST
    do
        if test -f $PROJECT_PATH/$FILENAME; then
            cp $PROJECT_PATH/$FILENAME $TEMPLATE_PATH/template
        else
            echo "WARNUNG: Datei $FILENAME nicht vorhanden."
        fi
    done
    
    # rename dot-files
    typeset -a DOT_FILES
    DOT_FILES=$(find ${TEMPLATE_PATH}/template/ -maxdepth 1 -type f -name ".*" -exec basename {} \;)
    
    for FILENAME in $DOT_FILES
    do
        NEWFILENAME=$(echo ${FILENAME} | tr '.' '_')
        mv $TEMPLATE_PATH/template/$FILENAME $TEMPLATE_PATH/template/$NEWFILENAME
    done

else

    echo "FEHLER: Ordner $TEMPLATE_PATH/template konnte nicht erstellt werden."

fi

# create 'package-lock.json' file
touch $TEMPLATE_PATH/package-lock.json

FILE="${TEMPLATE_PATH}/package-lock.json"

/bin/cat <<EOM >$FILE
{
  "name": "${TEMPLATE_NAME}",
  "version": "$TEMPLATE_VERSION",
  "lockfileVersion": $LOCK_FILE_VERSION
}
EOM

# create 'package.json' file
touch $TEMPLATE_PATH/package.json
FILE="${TEMPLATE_PATH}/package.json"

/bin/cat <<EOM >$FILE
{
  "name": "${TEMPLATE_NAME}",
  "version": "$TEMPLATE_VERSION",
  "description": "$DESCRIPTION",
  "scripts": {
    "prepublishOnly": ""
  },
  "files": [
    "template",
    "template.config.js"
  ],
  "repository": {
    "type": "git",
    "url": ""
  },
  "keywords": [
    "react-native",
    "typescript",
    "jest",
    "template",
    "boilerplate",
    "redux",
    "react-navigation",
    "native-base",
    "i18next"
  ],
  "author": "${AUTHOR} <${AUTHOR_MAIL}>",
  "license": "MIT",
  "homepage": "$HOMEPAGE"
}
EOM

# create 'template.config.js' file 
touch $TEMPLATE_PATH/template.config.js
FILE="${TEMPLATE_PATH}/template.config.js"

/bin/cat <<EOM >$FILE
module.exports = {
  placeholderName: 'HelloWorld',
  templateDir: './template',
}
EOM

# create '.gitignore' file 
touch $TEMPLATE_PATH/.gitignore
FILE="${TEMPLATE_PATH}/.gitignore"

/bin/cat <<EOM >$FILE
node_modules/
.vscode/
.DS_Store
EOM

# create 'README.md' file 
touch $TEMPLATE_PATH/README.md
FILE="${TEMPLATE_PATH}/README.md"

/bin/cat <<EOM >$FILE
${TEMPLATE_NAME} - README file
EOM

exit

Das heruntergeladene Skript entpacken und ausführbar machen:

$ tar xvzf create-react-native-template.tar.gz
$ chmod +x create-react-native-template.sh

Das Skript konfigurieren (Pfade und Werte anpassen) und ausführen:

$ ./create-react-native-template.sh

Projekt aus dem Template erstellen

$ npx react-native init YourAppName --template file:///home/$USER/path/to/your/template/folder

 

War diese Seite für dich informativ? Hat sie dir gefallen und geholfen?

Dann unterstütze die Weiterentwicklung mit einer kleinen Spende!

Die Spenden werden für die Lizenzen sowie neue Hard- und Software verwendet, die für weitere Projekte auf dieser Webseite eingesetzt werden.





React Native: Projekt einrichten




Vor der weiteren Arbeit an einem neu angelegtem Projekt, kann man einige standardmäßig benötigten Pakete hinzufügen und einrichten.

Redux installieren und einrichten

Installieren

Siehe: Nützliche Pakete – Redux

Redux wird auch Async Storage benötigen. Eine Installationsanleitung befindet sich hier.

Einrichten

Den Projektordner im Visual Studio Code öffnen.

Einen Unterordner src erstellen.

VSCode_src_erstellen [Image]

Actions erstellen

Actions beschreiben ein Ereignis zum Speichern der Daten.

In dem src-Ordner einen weiteren Unterodrdner actions erstellen und in diesem zwei Dateien anlegen: appActions.ts und userActions.ts.

Die src/actions/appActions.ts-Datei enthält die Aktionen zum Setzen der App-Einstellungen wie z.B. die Sprache oder ein Passwort.

src/actions/appActions.ts

export const SET_SELECTED_LANGUAGE = 'APP/SET_SELECTED_LANGUAGES';
export const SET_PASSWORD = 'APP/SET_PASSWORD';

export type AppActionTypes = SetSelectedLanguage | SetPassword;

interface SetSelectedLanguage {
  type: typeof SET_SELECTED_LANGUAGE;
  payload: SetSelectedLanguagePayload;
}

interface SetSelectedLanguagePayload {
  selectedLanguage: string;
}

interface SetPassword {
  type: typeof SET_PASSWORD;
  payload: SetPasswordPayload;
}

interface SetPasswordPayload {
  password: string;
}

export function setSelectedLanguage(selectedLanguage: string): SetSelectedLanguage {
  return {
    type: SET_SELECTED_LANGUAGE,
    payload: {
      selectedLanguage,
    },
  };
}

export function SetPassword(password: string): SetPassword {
  return {
    type: SET_PASSWORD,
    payload: {
      password,
    },
  };
}

In die Datei src/actions/userActions.ts werden die Aktionen zum Setzen der Benutzerdaten eingefügt.

src/actions/userActions.ts

export const SET_FIRST_NAME = 'USER/SET_FIRST_NAME';
export const SET_LAST_NAME = 'USER/SET_LAST_NAME';
export const SET_PHONE_NUMBER = 'USER/SET_PHONE_NUMBER';
export const SET_EMAIL_ADDRESS = 'USER/SET_EMAIL_ADDRESS';

export type UserActionTypes = SetFirstName | SetLastName | SetPhoneNumber | SetEmailAddress;

interface SetFirstName {
  type: typeof SET_FIRST_NAME;
  payload: SetFirstNamePayload;
}

interface SetFirstNamePayload {
  firstName: string;
}

interface SetLastName {
  type: typeof SET_LAST_NAME;
  payload: SetLastNamePayload;
}

interface SetLastNamePayload {
  lastName: string;
}

interface SetPhoneNumber {
  type: typeof SET_PHONE_NUMBER;
  payload: SetPhoneNumberPayload;
}

interface SetPhoneNumberPayload {
  phoneNumber: string;
}

interface SetEmailAddress {
  type: typeof SET_EMAIL_ADDRESS;
  payload: SetEmailAddressPayload;
}

interface SetEmailAddressPayload {
  emailAddress: string;
}

export function setFirstName(firstName: string): SetFirstName {
  return {
    type: SET_FIRST_NAME,
    payload: {
      firstName,
    },
  };
}

export function setLastName(lastName: string): SetLastName {
  return {
    type: SET_LAST_NAME,
    payload: {
      lastName,
    },
  };
}

export function setPhoneNumber(phoneNumber: string): SetPhoneNumber {
  return {
    type: SET_PHONE_NUMBER,
    payload: {
      phoneNumber,
    },
  };
}

export function setEmailAddress(emailAddress: string): SetEmailAddress {
  return {
    type: SET_EMAIL_ADDRESS,
    payload: {
      emailAddress,
    },
  };
}


Reducer erstellen

Ein Reducer  gibt an wie der Anwendungzustand sich ändert im Bezug auf die ausgelöste Aktion.

In dem src-Ordner einen neuen Unterordner reducers erstellen.

Diesem src/reducers-Ordner drei Dateien hinzufügen: appReducer.ts, userReducer.ts und index.ts.

src/reducers/appReducer.ts

import {
  SET_SELECTED_LANGUAGE, SET_PASSWORD, AppActionTypes,
} from '../actions/appActions';

export interface AppState {
  selectedLanguage: string;
  password: string;
}

const initialState: AppState = {
  selectedLanguage: 'en',
  password: '',
};

const appReducer = (
  state = initialState,
  action: AppActionTypes,
): AppState => {
  switch (action.type) {
    case SET_SELECTED_LANGUAGE:
      return {
        ...state,
        selectedLanguage: action.payload.selectedLanguage,
      };
    case SET_PASSWORD:
      return {
        ...state,
        password: action.payload.password,
      };
    default:
      return state;
  }
};

export default appReducer;

src/reducers/userReducer.ts

import {
  SET_FIRST_NAME, SET_LAST_NAME, SET_PHONE_NUMBER, SET_EMAIL_ADDRESS,
  UserActionTypes,
} from '../actions/userActions';

export interface UserState {
  firstName: string;
  lastName: string;
  phoneNumber: string;
  emailAddress: string;
}

const initialState: UserState = {
  firstName: '',
  lastName: '',
  phoneNumber: '',
  emailAddress: '',
};

const userReducer = (
  state = initialState,
  action: UserActionTypes,
): UserState => {
  switch (action.type) {
    case SET_FIRST_NAME:
      return {
        ...state,
        firstName: action.payload.firstName,
      };
    case SET_LAST_NAME:
      return {
        ...state,
        lastName: action.payload.lastName,
      };
    case SET_PHONE_NUMBER:
      return {
        ...state,
        phoneNumber: action.payload.phoneNumber,
      };
    case SET_EMAIL_ADDRESS:
      return {
        ...state,
        emailAddress: action.payload.emailAddress,
      };
    default:
      return state;
  }
};

export default userReducer;

src/recucers/index.ts

import { combineReducers } from 'redux';
import userReducer from './userReducer';
import appReducer from './appReducer';

const rootReducer = combineReducers({
  user: userReducer,
  app: appReducer,
});

export default rootReducer;

Dem src-Ordner eine neue Datei configureStore.ts hinzufügen.

src/configureStore.ts

import { createStore, Store } from 'redux';
import { persistReducer, persistStore } from 'redux-persist';
import AsyncStorage from '@react-native-community/async-storage';
import { Persistor } from 'redux-persist/es/types';
import rootReducer from './reducers';

interface ConfigureStore {
  store: Store;
  persistor: Persistor;
}

const persistConfig = {
  key: 'root',
  storage: AsyncStorage,
};

const persistedReducer = persistReducer(persistConfig, rootReducer);

export default (): ConfigureStore => {
  const store = createStore(persistedReducer);
  const persistor = persistStore(store);
  return { store, persistor };
};

Hinweis: Für Mozilla Firefox und Google Chrome gibt es Redux DevTools Extension Add-Ons, die die Entwicklungsarbeit mit Redux erleichtern. Siehe: Nützliche Pakete – Redux DevTools.

i18next instellieren und einrichten.

Auch wenn man beabsichtigt die App einsprachig zu entwickeln, lohnt es die Installation und Nutzung der Internationalisierung im Quellcode . Man weiß nicht ob die Entscheidung sich zum spätern Zeitpunkt ändert. Sind die Text-Strings im Quellcode mit der Übersetzungssynthax versehen, muss nur die JSON-Übersetzungsdatei hinzugefügt werden, anstatt die ganzen Quellcode Text-Strings nachträglich zu modifizieren.

Installieren

Siehe: Nützliche Pakete – i18next

Einrichten

In dem src-Ordner einen Unterordner types erstellen und diesem eine default.ts-Datei hinzufügen. Sie enthält die Standard-Datentypen der Anwendung.

src/types/default.ts

import React from 'react';

export interface DefaultProps {
  children?: React.ReactNode;
}

In dem src-Ordner einen weiteren Unterordner translations für die Übersetzungsdateien erstellen.

src/translations/en.json

{
  "general": {
    "loading": "Load...",
    "save": "Save",
    "messages": {
      "someMessage": "Some Message"
    },
    "errors": {
      "unknown": "Unknown error occurred!"
    }
  },
  "profile": {
    "headerTitle": "Personal Data",
    "fields": {
      "firstName": "first name",
      "lastName": "family name",
      "phoneNumber": "phone number",
      "emailAddress": "email Address"
    }
  },
  "home": {
    "headerTitle": "Home"
  },
  "settings": {
    "headerTitle": "Settings",
    "selectLanguage": "Select the Language",
    "language": "Language",
    "languages": {
      "german": "German",
      "english": "English"
    },
    "password": "Password",
    "savePassword": "Password successfully changed"
  }
}

src/translations/de.json

{
  "general": {
    "loading": "Laden...",
    "save": "Speichern",
    "messages": {
      "someMessage": "Irgendeine Nachricht"
    },
    "errors": {
      "unknown": "Unbekannter Fehler aufgetreten!"
    }
  },
  "profile": {
    "headerTitle": "Persönliche Daten",
    "fields": {
      "firstName": "Vorname",
      "lastName": "Familienname",
      "phoneNumber": "Telefonnummer",
      "emailAddress": "E-Mail-Adresse"
    }
  },
  "home": {
    "headerTitle": "Start"
  },
  "settings": {
    "headerTitle": "Einstellungen",
    "selectLanguage": "Wähle die Sprache",
    "language": "Sprache",
    "languages": {
      "german": "Deutsch",
      "english": "Englisch"
    },
    "password": "Passwort",
    "savePassword": "Passwort erfolgreich geändert"
  }
}

Damit die JSON-Objekte in JavaScript importiert werden können, muss diese Option in der TypeScript-Konfigurationsdatei aktiviert werden.

tsconfig.json

{
  "compilerOptions": {
    /* Basic Options */
    "target": "esnext",                       /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    "lib": ["es6"],                           /* Specify library files to be included in the compilation. */
    "allowJs": true,                          /* Allow javascript files to be compiled. */
    // "checkJs": true,                       /* Report errors in .js files. */
    "jsx": "react-native",                    /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
    // "sourceMap": true,                     /* Generates corresponding '.map' file. */
    // "outFile": "./",                       /* Concatenate and emit output to single file. */
    // "outDir": "./",                        /* Redirect output structure to the directory. */
    // "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    // "removeComments": true,                /* Do not emit comments to output. */
    "noEmit": true,                           /* Do not emit outputs. */
    "incremental": true,                      /* Enable incremental compilation */
    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    "isolatedModules": true,                  /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
    "resolveJsonModule": true,                /* Convert JSON-Code to Javascript */

    /* Strict Type-Checking Options */
    "strict": true,                           /* Enable all strict type-checking options. */
    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true,              /* Enable strict null checks. */
    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    // "noUnusedLocals": true,                /* Report errors on unused locals. */
    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */

    /* Module Resolution Options */
    "moduleResolution": "node",               /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    "baseUrl": "./",                          /* Base directory to resolve non-absolute module names. */
    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* List of folders to include type definitions from. */
    // "types": [],                           /* Type declaration files to be included in compilation. */
    "allowSyntheticDefaultImports": true,     /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true                   /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */

    /* Source Map Options */
    // "sourceRoot": "./",                    /* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "./",                       /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    /* Experimental Options */
    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
  },
  "exclude": [
    "node_modules", "babel.config.js", "metro.config.js", "jest.config.js"
  ]
}

Zuletzt wird noch der Übersetzer implementiert.

src/i18nGate.tsx

import React from 'react';
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import { useSelector } from 'react-redux';
import * as TranslationDE from './translations/de.json';
import * as TranslationEN from './translations/en.json';
import { AppState } from './reducers/appReducer';
import { DefaultProps } from './types/default';


const I18nGate = (props: DefaultProps): React.FunctionComponentElement<DefaultProps> => {
  const { children } = props;
  const selectedLanguage = useSelector((state: { app: AppState}) => state.app.selectedLanguage);

  i18n.use(initReactI18next).init({
    resources: {
      de: {
        translation: {
          ...TranslationDE,
        },
      },
      en: {
        translation: {
          ...TranslationEN,
        },
      },
    },
    lng: selectedLanguage,
    fallbackLng: 'en',

    interpolation: {
      escapeValue: false,
    },
  });

  return (
    // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
    // @ts-ignore
    { ...children }
  );
};

export default I18nGate;


React Navigation installieren

Siehe: Nützliche Pakete – React Navigation

NativeBase installieren

Siehe: Nützliche Pakete – NativeBase

 

War diese Seite für dich informativ? Hat sie dir gefallen und geholfen?

Dann unterstütze die Weiterentwicklung mit einer kleinen Spende!

Die Spenden werden für die Lizenzen sowie neue Hard- und Software verwendet, die für weitere Projekte auf dieser Webseite eingesetzt werden.





React Native: Nützliche Pakete




Die folgende Liste enthält nützliche npm-Pakete und Module für React Native, die nachträglich installiert werden können um die App-Funktionalität zu erweitern.

Async Storage

Asynchrones Key-Value Speichersystem. Es wird in Verbindung mit Redux benutzt.

$ npm install @react-native-community/async-storage

Webseiten:

Async Storage: https://www.npmjs.com/package/@react-native-community/async-storage

Async Storage auf Git: https://github.com/react-native-community/async-storage/tree/master

axios

Native ES6 Promise-basierter HTTP-Client für den Browser und Node.js.

$ npm install axios

Webseite: https://www.npmjs.com/package/axios

buffer

Ein Buffer-Modul für den Browser.

$ npm install buffer

Webseite: https://www.npmjs.com/package/buffer

i18next

Internationalisierungs-Framework. Es wird benutzt um Apps in verschiedene Ländersprachen zu übersetzen.

react-i18next ist ein Internationalisierungs-Framework für React und React Native, das auf i18next basiert.

$ npm install --save i18next react-i18next

Webseiten:

i18next: https://www.i18next.com/

react-i18next: https://react.i18next.com/

NativeBase

Komponenten-Bibliothek für die Android– und iOS-Benutzeroberflächen.

$ npm install native-base --save
$ npx react-native link

Webseite: https://nativebase.io/

React Navigation

Routing und Navigation für React Native Apps.

react-navigation ist das Kernpaket zur Erstellung von Routen und Navigationen.

react-native-gesture-handler ist ein Benutzeroberflächen-Berührungs- und Bewegungssystem.

react-native-reanimated erweitert das React Native Animationspaket Animated.

react-native-screens stellt der react-navigation verschiedene Screen-Darstellungen wie Stack, Tab, Drawer usw. zur Verfügung.

react-native-safe-area-context dient der Bedienung der SafeArea.

$ npm install react-navigation react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context

Verlinken auf iOS

cd ios
pod install
cd ..

Verlinken auf Android

Die react-native-screens Installation vervollständigen, indem die zwei Zeilen in die Sektion dependencies in der Datei android/app/build.gradle hinzugefügt werden.

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "com.facebook.react:react-native:+"  // From node_modules
    implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
    implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha02'

    if (enableHermes) {
        def hermesPath = "../../node_modules/hermes-engine/android/";
        debugImplementation files(hermesPath + "hermes-debug.aar")
        releaseImplementation files(hermesPath + "hermes-release.aar")
    } else {
        implementation jscFlavor
    }
}

Die react-native-gesture-handler Installation durch die Ergänzung der Datei android/app/src/main/java/com/<projectname>/MainActivity.java abschließen.

package com.reactnativedemo;

import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;

public class MainActivity extends ReactActivity {

  /**
   * Returns the name of the main component registered from JavaScript. This is used to schedule
   * rendering of the component.
   */
  @Override
  protected String getMainComponentName() {
    return "ReactNativeDemo";
  }

  @Override
  protected ReactActivityDelegate createReactActivityDelegate() {
    return new ReactActivityDelegate(this, getMainComponentName()) {
       @Override
        protected ReactRootView createRootView() {
         return new RNGestureHandlerEnabledRootView(MainActivity.this);
       }
    };
  }
}

Der Einstiegsdatei index.js oder App.js die folgende Zeile hinzufügen:

/**
 * @format
 */

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

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

Webseiten:

react-navigation: https://reactnavigation.org/

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

react-native-reanimated: https://github.com/software-mansion/react-native-reanimated

react-native-screens: https://github.com/kmagiera/react-native-screens

react-native-safe-area-context: https://github.com/th3rdwave/react-native-safe-area-context

Redux

redux ist ein globaler App-State-Container.

react-redux ist die offizielle React-Bindung an Redux. Sie erlaut den React-Komponenten das Interagieren mit dem Redux-Store.

redux-persist speichert dauerhaft ein Redux-Objekt. Wird die App neu gestartet, wird das Objekt mit den States wieder in Redux geladen, so dass die App den ursprünglichen Zustand erhält.

$ npm install redux react-redux redux-persist

Zusätzlich die React-Redux-Typen-Entwicklungsabhängigkeiten (devDependencies) installieren:

$ npm install --save-dev @types/react-redux

Webseiten:

redux: https://redux.js.org/

react-redux: https://react-redux.js.org/

redux-persist: https://github.com/rt2zz/redux-persist

Redux DevTools

Redux DevTools sind Add-Ons für die Browser Mozilla Firefox und Google Chrome mit grafischen Redux-Entwicklungswerkzeugen.

Redux DevTools für Mozilla Firefox

Siehe: https://addons.mozilla.org/en-US/firefox/addon/reduxdevtools/

Redux DevTools für Google Chrome

Siehe: https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd

Im React Native Projekt installieren

Siehe: https://github.com/zalmoxisus/redux-devtools-extension

Socket.IO

Echtzeit-Kommunikation zwischen Webclients und Servern.

Die Bibliothek besteht aus zwei Paketen. Dem Server socket.io und dem Client socket.io-client.

Server installieren:

$ npm install socket.io

Client installieren:

$ npm install socket.io-client

Webseiten:

socket.io: https://socket.io/

socket.io auf Git: https://github.com/socketio/socket.io

socket.io-client auf Git: https://github.com/socketio/socket.io-client

 

War diese Seite für dich informativ? Hat sie dir gefallen und geholfen?

Dann unterstütze die Weiterentwicklung mit einer kleinen Spende!

Die Spenden werden für die Lizenzen sowie neue Hard- und Software verwendet, die für weitere Projekte auf dieser Webseite eingesetzt werden.