Эпилог.
Функциональность чата обязательна почти в каждом современном приложении, и у разработчиков интерфейса часто возникают проблемы с выполнением этой задачи со странными бэкенд-парнями :)
Что, если я скажу вам, что для этого вам не нужен бэкенд?
Что, если я скажу вам, что вы можете как минимум поговорить один на один за 15 минут?
Что, если я скажу вам, что вашим клиентам будет намного дешевле?
Наша цель:
Эпизод 1. Настройка
Что нам понадобится из пакетов?
- react-native-firebase - это будет наш бэкэнд и наш хост pub-sub (Websockets). Вы можете найти пакет здесь. Нам нужно будет инициализировать
CocoaPods
для приложения Firebase для iOS. - lodash - просто чтобы наш код был чище. Вы можете найти пакет здесь.
Итак, начнем с инициализации пустого проекта:
react-native init SimpleChat
Теперь давайте сразу добавим необходимые пакеты:
yarn add lodash && yarn add firebase
ВАЖНО: пока не делайте react-native link
!
Android
Официальное руководство по установке. Лучше использовать официальное руководство по установке, поскольку оно достаточно подробное.
iOS
Официальное руководство по установке, или вы можете прочитать дальше, мы сделаем это шаг за шагом.
Хорошо, поскольку Android установлен, мы можем начать с CocoaPods
. Я предполагаю, что вы используете Mac
или уже установили Ruby
(да, он еще не умер). Если вы этого не сделаете, следуйте инструкциям здесь, чтобы установить RVM
и Ruby
.
Давайте инициализируем CocoaPods
, подробнее, как установить CocoaPods
, можно найти здесь.
Перейдите в папку /ios
и запустите:
pod init
Вы увидите, что теперь в папке /ios
есть Podfile
(package.json
аналог в CocoaPods
мире) и SimpleChat.xcworkspace
. Это означает, что в вашем проекте установлено CocoaPods
.
ВАЖНО: Если вы используете Xcode, откройте свой проект, нажав SimpleChat.xcworkspace
вместо .xcodeproj
файл.
Теперь мы готовы к react-native link
, перейдите в корень вашего проекта и выполните:
react-native link
В настоящее время эта команда имеет две цели:
- Это добавит
Firebase/Core
к вашемуPodfile
. - Он обновит этап сборки и свяжет библиотеку Firebase с вашим проектом.
Нам по-прежнему нужны две дополнительные библиотеки из пакета Firebase:
Firebase/Firestore
- База данных FirebaseFirebase/Auth
- авторизация с помощью Firebase (например, если у вас есть бэкэнд, вам нет смысла его устанавливать, но в этом руководстве мне это нужно для идентификации пользователей)
Итак, давайте обновим наш /ios/Podfile
и добавим несколько строк кода. Теперь это должно выглядеть так:
platform :ios, '9.0' target 'SimpleChat' do pod 'Firebase/Core', '~> 5.20.2' pod 'Firebase/Firestore', '~> 5.20.2' pod 'Firebase/Auth', '~> 5.20.2' end
ПРИМЕЧАНИЕ. Не забудьте удалить ненужное из файла, если вы знаете, что делаете.
Когда react-native link
закончится и вы добавили необходимые пакеты, теперь вам нужно перейти в папку /ios
и запустить:
pod install
Теперь нам нужно изменить наш AppDelegate.m
и добавить две строки кода, сначала рядом с вами import:
#import <Firebase.h>
Второй внутри didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
сразу после определения:
[FIRApp configure];
Все библиотеки установлены. Теперь нам нужно настроить само приложение Firebase.
Эпизод 2. Приложение Firebase
Перейти в консоль Firebase. Если у вас нет учетной записи, создайте ее. Это бесплатно.
Создайте новый проект и введите его название:
Теперь нам нужно настроить Authentication
, опять же, если у вас есть бэкэнд, этот шаг вам не нужен.
Перейдите к Authentication
›Setup sign-in method
и выберите способ получения, который соответствует вашим потребностям. Для этого урока будет достаточно анонимной аутентификации:
Теперь нам нужно включить Firestore, перейти к Database
›Create database
› Выбрать режим (для этого урока - я использую test mode
, этого будет достаточно). Если вы все сделали правильно, вы должны увидеть страницу управления базой данных:
Отлично, сервисы готовы, теперь давайте создадим приложение для iOS и Android. Перейдите к Project Overview
›Выберите ОС, которая вам нужна (в этом уроке у меня есть только проект iOS, но он одинаково хорошо работает как на Android, так и на iOS.
Для обеих ОС просто следуйте инструкциям в консоли firebase (за исключением шага, который вы уже сделали, после успешного завершения установки вы получите файл конфигурации.
Android
Поместите свой google-service.json
в /android/app
:
iOS
Поместите свой GoogleService-Info.plist
в корень Xcode:
Теперь мы настроены. Давайте код.
Эпизод 3. Разметка
Я буду писать все с React Hooks
, но у вас будет пример без хуков в репозитории.
Наше дерево проекта будет выглядеть так:
|- /SimpleChat | |- /src | | |- /components | | | |- /common | | | | |- /Button | | | | | |- /index.js | | | | | |- /styles.js | | | | |- /Loader | | | | | |- /index.js | | | | | |- /styles.js | | | |- /HooksExample | | | | |- /index.js | | | | |- /reducers.js | | | |- /Input | | | | |- /index.js | | | | |- /styles.js | | | |- /Message | | | | |- /index.js | | | | |- /styles.js | | |- /constants | | | |- /collection.js | | | |- /index.js | | |- /services | | | |- /index.js | | | |- /FirebaseService.js | | |- /styles | | | |- /chat-room.js | | | |- /colors.js | | | |- /index.js | | |- /index.js | | |- /contexts.js
Немного подробностей о структуре:
/src/context.js
- это место, куда мы собираемся поместить весь наш контекст (например,currentUser
)./src/styles/chat-room.js
- это просто стили, так как я собираюсь повторно использовать их в примере компонента класса, а стили здесь помещены только для СУХОЙ (не повторяйте себя). Как обычно, вы можете поместить под себя папку с компонентами, в данном случае, например,HooksExample
./src/components/HooksExample/reducers.js
- это место, где я кладу сложную логику с крючками./src/services/FirebaseService.js
- это место, где мы будем общаться с firebase./src/constants/collections.js
- это место, где мы сохраняем имя нашей коллекции firebase
Начнем с нашего основного компонента. В следующей части мы напишем нашу логику.
Так что сейчас мы будем работать без разметки компонентов. Обычно все чаты имеют две части экрана: сообщения и кнопку ввода плюс для создания сообщений.
Мы собираемся создать наш главный компонент, давайте назовем его HooksExample
в этом руководстве, но собственное имя для него будет Chat
component. Он будет отображать FlatList
с нашими сообщениями и Input
компонент, в который мы собираемся заполнить наши сообщения и отправить их.
Итак, начнем с нашего Input
компонента. Позволяет код:
import React, { useCallback, useState } from 'react' import { View, TextInput } from 'react-native' import Button from '../common/Button' import styles from './styles' export default function Input () { const [message, setMessage] = useState('') const handlePress = useCallback( function () { // todo this }, [message] ) return ( <View style={styles.container}> <View style={styles.inputContainer}> <TextInput style={styles.input} value={message} onChangeText={setMessage} placeholder="Write you message" /> </View> <Button text="Send" onPress={handlePress} /> </View> ) }
И наши стили:
import { StyleSheet } from 'react-native' import { COLORS } from '../../styles' export default StyleSheet.create({ container: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-around', width: '100%' }, inputContainer: { width: '70%' }, input: { height: 40, borderColor: COLORS.GREY, borderWidth: 1, borderRadius: 3, flexDirection: 'row', paddingHorizontal: 10 } })
Вот что мы получим схематично:
Теперь давайте нацелимся на компонент Message
:
import React from 'react' import { View, Text } from 'react-native' import { styles, flattenedStyles } from './styles' export default function Message ({ message, side }) { const isLeftSide = side === 'left' const containerStyles = isLeftSide ? styles.container : flattenedStyles.container const textContainerStyles = isLeftSide ? styles.textContainer : flattenedStyles.textContainer const textStyles = isLeftSide ? flattenedStyles.leftText : flattenedStyles.rightText return ( <View style={containerStyles}> <View style={textContainerStyles}> <Text style={textStyles}> {message} </Text> </View> </View> ) }
Этот компонент принимает два props
:
message
- текст, строкаside
- строка, это будетleft
илиright
. И это поможет компоненту выбрать стили для компонента сообщения.
Нам нужно применить разные стили для левой и правой стороны. Вот как это выглядит в стилях:
import { StyleSheet } from 'react-native' import { COLORS } from '../../styles' const styles = StyleSheet.create({ container: { width: '100%', paddingVertical: 3, paddingHorizontal: 10, flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start' }, textContainer: { width: 160, backgroundColor: COLORS.GREY, borderRadius: 40, paddingHorizontal: 15, paddingVertical: 12, marginLeft: 10 }, rightContainer: { justifyContent: 'flex-end' }, rightTextContainer: { backgroundColor: COLORS.PRIMARY, marginRight: 10 }, leftText: { textAlign: 'left' }, rightText: { textAlign: 'right' }, text: { fontSize: 12 } }) const flattenedStyles = { container: StyleSheet.flatten([styles.container, styles.rightContainer]), textContainer: StyleSheet.flatten([styles.textContainer, styles.rightTextContainer]), leftText: StyleSheet.flatten([styles.leftText, styles.text]), rightText: StyleSheet.flatten([styles.rightText, styles.text]) } export { styles, flattenedStyles }
Теперь причина, по которой я создаю объект с именем flattenedStyles
, заключается в создании массива стилей с идентификатором. Этот механизм предоставляется нам StyleSheet
и помогает выполнять простую оптимизацию.
У нас есть и Message
, и Input
компоненты, и мы должны объединить их в наш HooksExample
компонент.
import React from 'react' import { FlatList, SafeAreaView, View } from 'react-native' import Input from '../Input' import Message from '../Message' import { chatRoomStyles as styles } from '../../styles' export default function HooksExample () { const mock = [ { id: 1, message: 'Hello', side: 'left' }, { id: 2, message: 'Hi!', side: 'right' } ] return ( <SafeAreaView> <View style={styles.messagesContainer}> <FlatList inverted data={} keyExtractor={function (item) { return item.id }} renderItem={function ({ item }) { return ( <Message side={data.side} message={data.message} /> ) }} /> </View> <View style={styles.inputContainer}> <Input /> </View> </SafeAreaView> ) }
И наши стили для HooksExample
компонента:
import { StyleSheet } from 'react-native' import COLORS from './colors' export default StyleSheet.create({ messagesContainer: { height: '100%', paddingBottom: 100 }, inputContainer: { width: '100%', height: 100, position: 'absolute', bottom: 0, paddingVertical: 10, paddingLeft: 20 borderTopWidth: 1, borderTopColor: COLORS.GREY } })
Итак, в итоге мы получим наценку за наш чат
Пролог.
Наша разметка готова, и мы можем написать свою логику. Посетите Чат за 30 минут с ReactNative и Firebase, серьезно! Pt. 2 . продолжить чтение…
В проекте в репозитории уже настроено приложение Firebase, и вы можете клонировать этот репозиторий и поэкспериментировать.