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.
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.