Навигатор стека

Навигация по экранам важна при работе с мобильными приложениями. React Navigation - потрясающая библиотека, которая позволяет вам создавать различные типы навигации в вашем проекте React Native.

Когда я впервые начал работать с React Native, я подумал, что это немного сбивает с толку, как перемещаться по экранам. Это было еще сложнее, потому что я хотел использовать Typescript и большинство примеров в Интернете, написанных с использованием Javascript.

Моя цель сейчас - показать вам, что я узнал, создавая несколько типов навигаторов с использованием Typescript, чтобы вы не страдали, как я вначале.

Итак, приступим к настройке базового Навигатора стека, который позволит вам перемещаться между экраном приветствия и входа в систему и экраном регистрации, как показано на следующем каркасе:

Настройте свой проект и React Navigation

Начнем с создания проекта на основе выставки. Убедитесь, что на вашем компьютере установлен expo. Если вы еще не установили его, вы можете сделать это, запустив:

npm install -g expo-cli

После установки давайте создадим проект, выполнив следующую команду,

expo init StackNavigatorExample

После того, как expo завершит инициализацию вашего проекта, вам нужно будет установить React Navigation и все зависимости, необходимые для его работы. Итак, приступим к настройке:

  1. cd в свой проект, запустив cd StackNavigatorExample

2. Установите React Navigation,

npm i @react-navigation/native

3. Установите одноранговые зависимости.

expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view

4. Установите Stack Navigator из React Navigation.

npm install @react-navigation/stack

5. Начни кодирование!

Создание структуры проекта и нашего навигатора

Теперь, когда у вас настроен наш проект, вы можете приступить к созданию всех экранов, которые будут обрабатываться навигатором. Начнем с создания структуры нашего проекта.

Давайте добавим следующие каталоги для хранения каждого экрана:

  • src/screens/Auth/LoginScreen
  • src/screens/Auth/SignupScreen
  • src/screens/WelcomeScreen

Ваш проект должен выглядеть так:

Теперь, когда у вас есть эта базовая структура проекта, давайте создадим навигатор. Чтобы сделать проект модульным, я создам отдельный каталог для всех моих навигаторов внутри src/navigators/AuthFlowNavigator/index.tsx.

index.tsxfile должен выглядеть так:

import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import WelcomeScreen from '../../screens/WelcomeScreen';
import LoginScreen from '../../screens/Auth/LoginScreen';
import SignupScreen, { SignupParams } from '../../screens/Auth/SignupScreen';
export enum AppScreens {
    Welcome = 'Welcome',
    Login = 'Login',
    Signup = 'Signup'
}
export type AuthStackParamList = {
    Login: undefined;
    Signup: SignupParams;
    Welcome: undefined;
};
const AuthStack = createStackNavigator<AuthStackParamList>();
const AuthFlowNavigator: React.FunctionComponent = () => {
    return (
        <AuthStack.Navigator headerMode="none">
            <AuthStack.Screen name={AppScreens.Welcome} component={WelcomeScreen} />
            <AuthStack.Screen name={AppScreens.Login} component={LoginScreen} />
            <AuthStack.Screen name={AppScreens.Signup} component={SignupScreen} />
        </AuthStack.Navigator>
    );
};
export default AuthFlowNavigator;

😮 Вам может быть интересно прямо сейчас, что делает весь этот код. Но это довольно просто. Я объясню это шаг за шагом,

  1. Определите перечисление с именами всех экранов в вашем приложении. Это позволит вам перемещаться между ними, не добавляя жестко запрограммированные имена внутри ваших экранов, это менее подвержено ошибкам, поскольку оно будет принимать связанное имя повсюду в вашем коде.
export enum AppScreens {
    Welcome = 'Welcome',
    Login = 'Login',
    Signup = 'Signup'
}

2. Определите, какие параметры можно передавать на каждый из экранов навигатора,

export type AuthStackParamList = {
    Login: undefined;
    Signup: SignupParams;
    Welcome: undefined;
};

Как мы видим в этом случае, единственный экран, который что-то получает, - это SignupScreen, мы скоро перейдем к определению его параметров.

3. Наконец, мы должны создать наш навигатор и экспортировать его, чтобы мы могли использовать его на нашем App.tsx, поскольку это точка входа в наше приложение.

const AuthStack = createStackNavigator<AuthStackParamList>();
const AuthFlowNavigator: React.FunctionComponent = () => {
    return (
        <AuthStack.Navigator headerMode="none">
            <AuthStack.Screen name={AppScreens.Welcome} component={WelcomeScreen} />
            <AuthStack.Screen name={AppScreens.Login} component={LoginScreen} />
            <AuthStack.Screen name={AppScreens.Signup} component={SignupScreen} />
        </AuthStack.Navigator>
    );
};
export default AuthFlowNavigator;

Как видите, я добавил в навигатор опору headerMode="none". По сути, он скрывает заголовок по умолчанию с кнопкой back, которую вы всегда получаете по умолчанию в навигаторе стека.

Еще одна вещь, которую следует учитывать в приведенном выше коде, - это то, что мы добавляем все экраны, которые хотим иметь в стеке, с помощью следующего кода:

<AuthStack.Screen name={AppScreens.Welcome} component={WelcomeScreen} />

В нашем примере мы просто добавляем 3 экрана: один для экрана приветствия, второй для экрана входа в систему и третий для экрана регистрации.

4. Обновите свой App.tsx файл, чтобы он выглядел следующим образом:

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import AuthFlowNavigator from './src/navigators/AuthFlowNavigator';
export default function App() {
    return (
        <NavigationContainer>
            <AuthFlowNavigator />
        </NavigationContainer>
    );
}

Таким образом, наш AuthFlowNavigator сможет отображать экран, который мы определили выше.

Экран приветствия

Теперь, когда у нас настроен навигатор, давайте добавим код на наш начальный экран (src/screens/WelcomeScreen/index.tsx),

import React from 'react';
import { SafeAreaView, StyleSheet, Text, View, Button } from 'react-native';
import { StackNavigationProp } from '@react-navigation/stack';
import { AuthStackParamList, AppScreens } from '../../navigators/AuthFlowNavigator';
type WelcomeScreenNavigationProps = StackNavigationProp<AuthStackParamList, AppScreens.Welcome>;
interface WelcomeScreenProps {
    navigation: WelcomeScreenNavigationProps;
}
const styles = StyleSheet.create({
    btnNextContainer: {
        alignSelf: 'flex-end'
    },
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'space-between',
        margin: 10
    },
    welcome: {
        fontSize: 30
    },
    welcomeContainer: {
        alignItems: 'center',
        justifyContent: 'center',
        flex: 1,
        width: '100%'
    }
});
const WelcomeScreen: React.FunctionComponent<WelcomeScreenProps> = (props) => {
    const { navigation } = props;
return (
        <SafeAreaView style={styles.container}>
            <View style={styles.welcomeContainer}>
                <Text style={styles.welcome}>Welcome</Text>
            </View>
            <View style={styles.btnNextContainer}>
                <Button title="NEXT" onPress={() => navigation.navigate(AppScreens.Login)} />
            </View>
        </SafeAreaView>
    );
};
export default WelcomeScreen;

Это должно дать вам следующий результат:

Как видно из следующего кода,

<Button title="NEXT" onPress={() => navigation.navigate(AppScreens.Login)} />

мы отображаем кнопку, которая позволяет нам перейти к следующему экрану в стеке. Посмотрите, как мы используем AppScreens.Login, перечисление, которое мы определили ранее и которое помогает нам узнать, какие экраны у него есть в нашем приложении, и предотвращает неправильный ввод имени экрана.

Экран входа в систему

Теперь давайте добавим код для LoginScreen внутрь src/screens/auth/LoginScreen/index.tsx. Должно получиться так:

import React, { useState } from 'react';
import { SafeAreaView, StyleSheet, Text, TextInput, Button, View } from 'react-native';
import { AppScreens, AuthStackParamList } from '../../../navigators/AuthFlowNavigator';
import { StackNavigationProp } from '@react-navigation/stack';
type LoginScreenNavigationProps = StackNavigationProp<AuthStackParamList, AppScreens.Login>;
interface LoginScreenProps {
    navigation: LoginScreenNavigationProps;
}
const styles = StyleSheet.create({
    btnSignupContainer: {
        alignItems: 'center'
    },
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'space-between',
        margin: 10
    },
    textInput: {
        borderRadius: 5,
        borderWidth: 1,
        borderColor: 'grey',
        marginTop: 4,
        padding: 2,
        width: '100%'
    },
    textInputContainer: {
        width: '100%'
    },
    txtHello: {
        fontSize: 30
    }
});
const LoginScreen: React.FunctionComponent<LoginScreenProps> = (props) => {
    const { navigation } = props;
    const [username, setUsername] = useState<string>('');
return (
        <SafeAreaView style={styles.container}>
            <Text style={styles.txtHello}>Hello</Text>
            <View style={styles.textInputContainer}>
                <TextInput
                    value={username}
                    placeholder="username"
                    style={styles.textInput}
                    onChangeText={(text) => setUsername(text)}
                />
                <TextInput placeholder="password" secureTextEntry={true} style={styles.textInput} />
            </View>
            <View style={styles.btnSignupContainer}>
                <Text>Or</Text>
                <Button title="Signup" onPress={() => navigation.navigate(AppScreens.Signup, { username })} />
            </View>
        </SafeAreaView>
    );
};
export default LoginScreen;

И это должно дать вам следующий результат:

Как вы можете видеть, код, связанный с навигацией, почти такой же по сравнению с WelcomeScreen, единственное главное отличие состоит в том, что мы передаем значениеusername в SignupScreen, передавая в качестве второго аргумента объект navigate(), содержащий всю необходимую нам информацию. перейти к следующему экрану:

<Button title="Signup" onPress={() => navigation.navigate(AppScreens.Signup, { username })} />

Экран регистрации

Наконец, добавьте следующий код к нашему SignupScreen по адресу src/screens/auth/SignupScreen/index.tsx,

import React from 'react';
import { SafeAreaView, StyleSheet, Text, TextInput, Button, View } from 'react-native';
import { AppScreens, AuthStackParamList } from '../../../navigators/AuthFlowNavigator';
import { StackNavigationProp } from '@react-navigation/stack';
type SignupScreenNavigationProps = StackNavigationProp<AuthStackParamList, AppScreens.Signup>;
export type SignupParams = {
    username: string;
};
interface SignupScreenProps {
    route: { params: SignupParams };
    navigation: SignupScreenNavigationProps;
}
const styles = StyleSheet.create({
    btnLoginContainer: {
        alignSelf: 'center'
    },
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'space-between',
        margin: 10
    },
    txtSignupScreen: {
        fontSize: 30
    },
    txtSignupScreenContainer: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center'
    },
    txtUsername: {
        fontSize: 25,
        color: 'grey'
    }
});
const SignupScreen: React.FunctionComponent<SignupScreenProps> = (props) => {
    const { navigation, route } = props;
    const { params } = route;
    const { username } = params;
return (
        <SafeAreaView style={styles.container}>
            <View style={styles.txtSignupScreenContainer}>
                <Text style={styles.txtSignupScreen}>SignupScreen</Text>
                <Text style={styles.txtUsername}>{username}</Text>
            </View>
            <View style={styles.btnLoginContainer}>
                <Text>have an account?</Text>
                <Button title="Login" onPress={() => navigation.pop()} />
            </View>
        </SafeAreaView>
    );
};
export default SignupScreen;

На этом экране вы заметите некоторые изменения по сравнению с предыдущим экраном. Здесь мы должны сообщить экрану, какие параметры он получает. Мы делаем это в этом разделе,

export type SignupParams = {
    username: string;
};
interface SignupScreenProps {
    route: { params: SignupParams };
    navigation: SignupScreenNavigationProps;
}

Приведенный выше код должен дать нам следующий результат:

Вы заметите, что благодаря выполненной настройке мы можем передавать значение username. Вы можете ввести что-нибудь в тексте username text field и нажать кнопку signup, и вы увидите значение, отображаемое на экране регистрации:

Заключение

Как видите, настроить навигатор с помощью React Navigation довольно просто. Если вы уже знакомы с некоторыми концепциями Typescript, то код, который мы рассмотрели, должен показаться вам довольно знакомым. Если вы используете Javascript в своем проекте, настройка навигатора работает точно так же, просто удалите все типы и интерфейсы, и все должно работать нормально.

Создание других типов навигаторов также действительно прямолинейно. После знакомства с React Navigation вы увидите, как легко добавлять новые экраны в свой проект!

Я загрузил репо в свою учетную запись GitHub на случай, если вы захотите клонировать его и сразу же использовать 😃

Https://github.com/gmotzespina/StackNavigatorExample