React — фантастическая библиотека для создания пользовательских интерфейсов. Выбирая серверную часть для использования вместе с ней, вы не ошибетесь с Firebase, серверной частью как услугой (Baas), которая упрощает добавление сохраняемости данных (и многое другое) в ваше приложение React.
В этом руководстве мы будем использовать Firebase вместе с приложением Create React для создания приложения, которое будет функционировать аналогично Reddit. Это позволит пользователю отправить новый пост, за который затем можно будет проголосовать. Я также покажу, как развернуть наш клон Reddit на Vercel.
Когда вы закончите читать, вы поймете, как настроить Firebase, как подключить его к вашему приложению React и как развернуть результат.
Изобретатель поместил сердце FireBase в создание робота
Почему Firebase?
Одной из сильных сторон Firebase является то, что он позволяет нам очень легко показывать пользователю данные в реальном времени. Как только пользователь проголосует за ссылку, обратная связь будет мгновенной. База данных реального времени Firebase поможет нам в разработке этой функции. Кроме того, это поможет нам понять, как загрузить приложение React с помощью Firebase.
Почему реагировать?
React особенно известен созданием пользовательских интерфейсов с использованием компонентной архитектуры. Каждый компонент может содержать внутреннее состояние или передавать данные как свойства. Состояние и свойства — две самые важные концепции в React. Эти две вещи помогают нам определить состояние нашего приложения в любой момент времени. Если вы не знакомы с этими терминами, сначала перейдите к документации React.
Примечание: вы также можете использовать контейнер состояния, такой как Redux или MobX, но для простоты мы не будем использовать его в этом руководстве.
Вот живая демонстрация того, что мы будем строить. Код этого приложения доступен на GitHub.
Настройка проекта
Чтобы продолжить, на вашем компьютере должны быть установлены Node и npm. Если нет, перейдите на страницу загрузки Node.js и скачайте последнюю версию для своей системы (npm поставляется вместе с Node). Кроме того, вы можете ознакомиться с нашим руководством по установке Node с помощью диспетчера версий.
Давайте рассмотрим шаги по настройке структуры нашего проекта и всех необходимых зависимостей.
Начальная загрузка приложения React
Мы можем создать новое приложение React с помощью Create React App, используя следующую команду:
npx
Это создаст новый
Структура каталога по умолчанию
После завершения начальной загрузки мы можем войти в
cd
На этом этапе мы можем посетить http: //localhost:3000/ и увидеть наше приложение в рабочем состоянии.
Страница по умолчанию приложения Create React
Структурирование приложения
Всегда рекомендуется удалять все файлы, которые нам не нужны, после загрузки любого приложения. Есть несколько файлов, сгенерированных приложением Create React, которые нам не понадобятся, поэтому мы их удалим.
Мы можем удалить следующие файлы:
src/App.css
src/App.test.js
src/index.css
src/logo.svg
src/serviceWorker.js
src/setupTests.js
Мы также можем удалить следующие зависимости из нашего package.jsonфайла:
@
@
@
Мы также можем удалить testскрипт из нашего package.jsonфайла. Это потому, что мы не будем писать тесты для нашего приложения. Если вы хотите изучить тестирование приложения React, обратитесь к нашему руководству «Как тестировать компоненты React с помощью Jest «.
Наш src/index.jsфайл должен содержать следующее:
import React from «react»;
import ReactDOM from «
import App from «. /app»;
ReactDOM.render (
,
document.getElementById («root»)
) ;
Мы переименуем наш src/App.jsв src/app.js. Измените его, чтобы он содержал следующее:
import React from «react»;
function App () {
return
;
}
export default App;
Теперь мы можем перезапустить наш сервер разработки, используя следующую команду из нашего корневого каталога:
npm start
Наш сервер разработки должен быть запущен и работать по адресу http: //localhost:3000/, и он должен выглядеть следующим образом:
Интерфейс нашего приложения после удаления ненужных файлов
Создание нового проекта Firebase
В этом разделе мы будем устанавливать и интегрировать Firebase с нашим приложением.
Если у вас нет учетной записи Firebase, вы можете создать одну бесплатную учетную запись прямо сейчас, посетив их
Введите название вашего проекта (я назову свой
Шаг 1 создания проекта Firebase
На следующем шаге вы должны выбрать, следует ли включить Google Analytics для проекта, затем нажмите кнопку «Продолжить «.
Шаг 2 создания проекта Firebase
На третьем шаге мы должны выбрать учетную запись Google Analytics, а затем нажать кнопку «Создать проект»:
Шаг 3 создания проекта Firebase
Через некоторое время вы увидите уведомление о том, что ваш новый проект готов. Нажмите «Продолжить», чтобы выйти из мастера.
Создание нового приложения в проекте Firebase
В этом разделе мы создадим новое приложение Firebase из консоли Firebase. Мы можем создать веб- приложение, выбрав
Создание нового
Далее нам нужно будет ввести название проекта и нажать кнопку «Зарегистрировать приложение «, оставив флажок «Также настроить Firebase Hosting» снятым.
Создание нового
Теперь вы увидите все учетные данные для нашего нового
Создание нового
Запишите эти учетные данные и нажмите «Продолжить для консоли «.
Теперь мы можем добавить учетные данные нашего приложения в файл среды:
//.env
REACT_APP_FIREBASE_API_KEY="123456"
REACT_APP_FIREBASE_AUTH_DOMAIN="reddit-clone-123456.firebaseapp.com"
REACT_APP_FIREBASE_PROJECT_ID="reddit-clone-123456"
REACT_APP_FIREBASE_STORAGE_BUCKET="reddit-clone-123456.appspot.com"
REACT_APP_FIREBASE_MESSAGING_SENDER_ID="123456"
REACT_APP_FIREBASE_APP_ID="1:123456:web:123456"
REACT_APP_FIREBASE_MEASUREMENT_ID="G-123456"
Примечание. Всегда рекомендуется хранить все учетные данные в файле среды и добавлять этот файл,.gitignoreчтобы учетные данные никогда не попадали в исходный код.
Затем мы можем создать новый файл, в src/lib/firebase.jsкотором будем хранить все наши учетные данные Firebase:
import firebase from «firebase»;
const firebaseConfig = {
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_FIREBASE_APP_ID,
measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID,
};
const initFirebase = firebase.initializeApp (firebaseConfig) ;
const db = initFirebase.firestore () ;
export default db;
Наконец, нам нужно установить пакет firebase, чтобы мы могли взаимодействовать с нашей базой данных:
npm install firebase
Добавление нового хранилища Firebase Cloud Firestore
Теперь нам нужно добавить новый Firebase Cloud Firestore — масштабируемую облачную базу данных NoSQL. Это можно сделать, выбрав ссылку Cloud Firestore и нажав кнопку «Создать базу данных «.
Создание нового Firebase Cloud Firestore
Далее мы выберем вариант запуска Firestore в рабочем режиме.
Выбор параметра для запуска Firebase Cloud Firestore в рабочем режиме
Нажмите «Далее». На следующем экране нам нужно выбрать расположение нашего облачного хранилища Firestore и нажать кнопку «Включить «.
Выбор местоположения Firebase Cloud Firestore
Вы увидите сообщение «Provisioning Cloud Firestore», за которым следует «Настройка правил безопасности «, и после небольшого ожидания вы будете перенаправлены на панель управления для вашего нового проекта.
Добавление новой коллекции в Firebase Cloud Firestore
Затем нам нужно добавить новую коллекцию в Firebase Cloud Firestore, которую мы только что создали. Мы можем сделать это, нажав кнопку «Начать сбор».
Добавление новой коллекции в Firebase Cloud Firestore: Шаг 1
Нам нужно добавить имя к нашему идентификатору коллекции. Мы можем назвать это постами, так как мы будем добавлять посты и голосовать за них.
Добавление новой коллекции в Firebase Cloud Firestore: Шаг 2
Нажмите «Далее». Пришло время добавить документ в нашу коллекцию. Для каждого документа требуется идентификатор, поэтому щелкните ссылку
Далее нам нужно добавить следующие поля:
Поле Тип Ценность Снимок экрана
создано на отметка времени Текущее время Добавление новой коллекции в Firebase Cloud Firestore: Шаг 3
обновлено отметка времени Текущее время Добавление новой коллекции в Firebase Cloud Firestore: Шаг 4
заглавие нить Это первый пост от Firebase Добавление новой коллекции в Firebase Cloud Firestore: Шаг 5
upVotesCount количество 0 Добавление новой коллекции в Firebase Cloud Firestore: Шаг 6
внизVotesCount количество 0 Добавление новой коллекции в Firebase Cloud Firestore: Шаг 7
Вот так в итоге будет выглядеть наша коллекция:
Добавление новой коллекции в Firebase Cloud Firestore: Шаг 8
Нажмите кнопку Сохранить. Коллекция будет создана, и вы будете перенаправлены на панель управления проекта.
Добавление новой коллекции в Firebase Cloud Firestore: Шаг 9
Обновление правил Firebase Cloud Firestore
Если мы перейдем на вкладку «Правила «, мы увидим следующие правила:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
Правила Firebase Cloud Firestore по умолчанию
Нам нужно изменить это, чтобы разрешить операцию записи:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
Наконец, нажмите кнопку «Опубликовать «, чтобы сохранить наши измененные правила:
Сохранение правил Firebase Cloud Firestore
Примечание: больше информации о правилах безопасности можно найти здесь.
Интеграция Firebase с приложением Create React
В этом разделе мы будем работать над нашим приложением React, чтобы добавить следующее:
Добавление пакета пользовательского интерфейса Chakra
Возможность просмотра всех сообщений
Возможность добавить новый пост
Возможность отключить кнопку голосования после того, как пользователь проголосовал за сообщение.
Добавление пакета пользовательского интерфейса Chakra
Мы добавим пакет пользовательского интерфейса Chakra, который поможет нам создать пользовательский интерфейс нашего приложения. Это простая, модульная и доступная библиотека компонентов React. Вы можете ознакомиться с их руководством по началу работы, если хотите узнать больше.
Мы можем установить Chakra UI, используя следующую команду:
npm install @
Чтобы пользовательский интерфейс Chakra работал правильно, нам нужно настроить ChakraProvider в корне приложения. Измените src/index.jsтак:
import { ChakraProvider } from «@
import React from «react»;
import ReactDOM from «
import App from «. /app»;
ReactDOM.render (
,
document.getElementById («root»)
) ;
Добавление опции для просмотра всех сообщений
В этом разделе мы создадим список для отображения всех наших сообщений из Firebase. Нам нужно изменить наш src/app.jsфайл следующим образом:
import { Container, Flex, Spinner, VStack } from «@
import React, { useEffect, useState } from «react»;
import Post from «. /components/post»;
import db from «. /lib/firebase»;
const App = () => {
const [posts, setPosts] = useState ([]) ;
useEffect (() => {
// Hook to handle the initial fetching of posts
db.collection («posts»)
.orderBy («createdAt», «desc»)
.get ()
.then ((querySnapshot) => {
const data = querySnapshot.docs.map ((doc) => ({
id: doc.id,
...doc.data (),
}));
setPosts (data) ;
}) ;
}, []) ;
return (
<>
{posts.map ((post) => (
))}
</>
) ;
};
export default App;
Здесь мы делаем следующее:
Хук useEffect отвечает за получение начального набора сообщений из Firebase. Надеюсь, синтаксис запроса относительно прост. Подробнее о выполнении запросов в Cloud Firestore можно прочитать здесь.
После того, как сообщения получены из Firebase, мы сохраняем все сообщения в postsсостоянии.
Мы отображаем список сообщений с помощью Postкомпонента.
Компонент Postотвечает за обработку рендеринга одного сообщения.
Далее нам нужно создать новый файл src/components/post.jsсо следующим содержимым:
import { Box, HStack, Text } from «@
import React from «react»;
const Post = ({ post }) => {
return (
) ;
};
export default Post;
Здесь мало что происходит. Компонент получает сообщение через свойства и отображает его заголовок в элементе Chakra UI Text.
Перезапустите сервер разработки, используя Ctrl+ C, затем посетите http: //localhost:3000/. Мы должны иметь возможность просматривать сообщение, которое мы ввели вручную в Firestore.
Рендеринг поста в пользовательском интерфейсе
Добавление возможности добавить новую запись
В этом разделе мы разработаем модальное окно, с помощью которого мы сможем добавить новый пост. Для этого нам нужно добавить в наш src/app.jsфайл следующий код:
...
import Navbar from «. /components/navbar»;
...
const App = () => {
...
return (
<>
...
</>
) ;
};
Нам также нужно добавить новый файл src/components/navbar.jsсо следующим содержимым:
import { Box, Container, Flex } from «@
import React from «react»;
import AddNewPost from «. /
const Navbar = () => {
return (
) ;
};
export default Navbar;
Нам также нужно добавить новый файл src/components/
import {
Button,
FormControl,
FormLabel,
Textarea,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
HStack,
useDisclosure,
} from «@
import React, { useState, useEffect } from «react»;
import db from «.../lib/firebase»;
const AddNewPost = () => {
const { isOpen, onOpen, onClose } = useDisclosure () ;
const [title, setTitle] = useState («») ;
const [isSaving, setSaving] = useState (false) ;
const handleSubmit = async () => {
const date = new Date () ;
await db.collection («posts»).add ({
title,
upVotesCount: 0,
downVotesCount: 0,
createdAt: date.toUTCString (),
updatedAt: date.toUTCString (),
}) ;
onClose () ;
setTitle («») ;
};
return (
<>
<Textarea
type="post-title"
value={title}
onChange={ (e) => setTitle (e.target.value) }
/>
<Button
onClick={handleSubmit}
colorScheme="blue"
disabled={! title.trim () }
isLoading={isSaving}
>
Save
</>
) ;
};
export default AddNewPost;
Компонент AddNewPostбудет отвечать за открытие модального окна для добавления нового поста. Мы используем хук useDisclosure от Chakra, пользовательский хук, помогающий обрабатывать распространенные сценарии открытия, закрытия или переключения.
Теперь, если мы посетим http: //localhost:3000/, мы сможем увидеть следующее:
Рендеринг панели навигации в пользовательском интерфейсе
Если мы нажмем кнопку «Добавить новый пост «, появится модальное окно, через которое мы можем добавить новый пост:
Добавление нового поста
Однако нам нужно обновить страницу, чтобы увидеть новую запись. Мы можем исправить это, добавив новый useEffectхук в наш src/app.jsфайл:
// src/app.js
useEffect (() => {
// Hook to handle the
// change in the datastore (https: //firebase.google.com/docs/firestore/
db.collection («posts»)
.orderBy («createdAt», «desc»)
.onSnapshot ((querySnapshot) => {
const _posts = [];
querySnapshot.forEach ((doc) => {
_posts.push ({
id: doc.id,
...doc.data (),
}) ;
}) ;
setPosts (_posts) ;
}) ;
}, []) ;
Теперь, если мы добавим новый пост, он будет виден в режиме реального времени.
Добавление нового поста и просмотр его в режиме реального времени
Добавление возможности голосовать за сообщение
В этом разделе мы разработаем кнопки, с помощью которых пользователь может голосовать за каждый пост. Для этого нам нужно добавить в наш src/components/post.jsфайл следующий код:
...
import VoteButtons from «. /
const Post = ({ post }) => {
return (
...
) ;
};
export default Post;
Далее нам нужно добавить новый файл src/components/
// src/components/
import { IconButton, Text, VStack } from «@
import React, { useState } from «react»;
import { FiArrowDown, FiArrowUp } from «
import db from «.../lib/firebase»;
const VoteButtons = ({ post }) => {
const handleClick = async (type) => {
// Do calculation to save the vote.
let upVotesCount = post.upVotesCount;
let downVotesCount = post.downVotesCount;
const date = new Date () ;
if (type === «upvote») {
upVotesCount = upVotesCount + 1;
} else {
downVotesCount = downVotesCount + 1;
}
await db.collection («posts»).doc (post.id).set ({
title: post.title,
upVotesCount,
downVotesCount,
createdAt: post.createdAt,
updatedAt: date.toUTCString (),
}) ;
};
return (
<>
<IconButton
size="lg"
colorScheme="purple"
icon={
onClick={ () => handleClick («upvote») }
/>
{post.upVotesCount}
<IconButton
size="lg"
colorScheme="yellow"
icon={
onClick={ () => handleClick («downvote») }
/>
{post.downVotesCount}
</>
) ;
};
export default VoteButtons;
Компонент VoteButtonsотвечает за рендеринг кнопки «за» и «против». Когда пользователь нажимает на любую из этих двух кнопок, handleClickвызывается функция. Функция handleClickотвечает за сохранение голосования в базе данных.
Поскольку мы используем значки из React Icons, нам нужно добавить файл package. Мы можем сделать это, выполнив следующую команду из нашего корневого каталога:
npm install
Теперь, если мы посетим http: //localhost:3000/, мы сможем увидеть следующее:
Добавляем кнопки голосования
Мы должны иметь возможность голосовать за любой из постов:
Голосование за каждый пост
Добавление возможности отключить кнопку голосования после того, как пользователь проголосовал за сообщение
В предыдущем разделе мы добавили возможность голосовать за пост. Однако мы видим, что пользователь может голосовать за один и тот же пост несколько раз. Мы можем исправить это, отключив кнопку голосования после того, как пользователь уже проголосовал за сообщение.
Для этого нам нужно добавить в наш src/component/
import React, { useEffect, useState } from «react»;
...
const VoteButtons = ({ post }) => {
const [isVoting, setVoting] = useState (false) ;
const [votedPosts, setVotedPosts] = useState ([]) ;
useEffect (() => {
// Fetch the previously voted items from localStorage. See https://stackoverflow.com/a/52607524/1928724 on why we need «JSON.parse» and update the item on localStorage. Return «true» if the user has already voted the post.
const votesFromLocalStorage = localStorage.getItem («votes») || [];
let previousVotes = [];
try {
// Parse the value of the item from localStorage. If the value of the
// items isn’t an array, then JS will throw an error.
previousVotes = JSON.parse (votesFromLocalStorage) ;
} catch (error) {
console.error (error) ;
}
setVotedPosts (previousVotes) ;
}, []) ;
const handleDisablingOfVoting = (postId) => {
// This function is responsible for disabling the voting button after a
// user has voted. Fetch the previously voted items from localStorage. See
// https://stackoverflow.com/a/52607524/1928724 on why we need «JSON.parse»
// and update the item on localStorage.
const previousVotes = votedPosts;
previousVotes.push (postId) ;
setVotedPosts (previousVotes) ;
// Update the voted items from localStorage. See https://stackoverflow.com/a/52607524/1928724 on why we need «JSON.stringify» and update the item on localStorage.
localStorage.setItem («votes», JSON.stringify (votedPosts));
};
const handleClick = async (type) => {
setVoting (true) ;
...
// Disable the voting button once the voting is successful.
handleDisablingOfVoting (post.id) ;
setVoting (true) ;
};
const checkIfPostIsAlreadyVoted = () => {
if (votedPosts.indexOf (post.id) > -1) {
return true;
} else {
return false;
}
};
return (
<>
<IconButton
...
isLoading={isVoting}
isDisabled={checkIfPostIsAlreadyVoted () }
/>
...
<IconButton
...
isLoading={isVoting}
isDisabled={checkIfPostIsAlreadyVoted () }
/>
...
</>
) ;
};
export default VoteButtons;
В приведенных выше изменениях мы делаем следующее:
Мы отслеживаем idсообщения, за которые проголосовали, в нашем локальном хранилище.
После того, как за сообщение проголосовали, мы добавляем его idв наш файл localStorage.
Мы отключаем кнопки голосования после того, как пользователь проголосовал за сообщение. Когда приложение отображает любые сообщения, за которые проголосовали, они будут отключены по умолчанию.
Отключение кнопки голосования после подачи голоса
Обратите внимание, что обычно вы храните такого рода информацию в базе данных. К сожалению, это выходит за рамки нашего приложения, так как это означало бы, что нам нужно будет реализовать целую систему управления пользователями и аутентификации.
Отправка изменений нашего кода на GitHub
Мы закончили с добавлением всех функций в наше приложение. В этом разделе мы зафиксируем наш код и отправим его на GitHub.
Создание учетной записи GitHub
Поскольку мы собираемся хранить наш код на GitHub, нам понадобится учетная запись GitHub. Обратите внимание, что это потребуется, когда мы приступим к развертыванию приложения на Vercel.
Коммит нашего кода с помощью Git
Для этого следующего шага вам понадобится установленный Git на вашем ПК. Если вы не знакомы с Git или хотите освежить свои знания, ознакомьтесь со
Из нашего корневого каталога мы можем запустить следующие команды для подготовки всех наших файлов:
git add —all
Примечание: более подробная информация git addдоступна здесь.
Затем мы можем зафиксировать наши файлы, используя следующую команду:
git commit -m «Adds all the necessary code»
Примечание: более подробная информация git commitдоступна здесь.
Создание нового репозитория GitHub
Мы можем создать новый репозиторий GitHub, посетив https://github.com/new.
Создание нового репозитория GitHub
Как только мы добавим имя в наш репозиторий, мы можем нажать кнопку «Создать репозиторий «, чтобы создать новый репозиторий.
Отправка кода в наш репозиторий GitHub
Мы можем отправить код в наш репозиторий GitHub, используя следующую команду:
git remote add origin https://github.com/ghoshnirmalya/reddit-clone-app.git
git branch -M main
git push -u origin main
Примечание. Вам необходимо заменить «https: //github.com/
Отправка кода в наш новый репозиторий GitHub
И это все. Наше приложение теперь находится под контролем версий и размещено на GitHub!
Развертывание приложения в Vercel
В этом последнем разделе мы развернем наш код в Vercel.
Создание учетной записи Vercel
Сначала зайдите в Vercel и создайте учетную запись. Вы можете войти с помощью GitHub, GitLab и BitBucket.
Импорт репозитория Git в Vercel
Мы можем импортировать наш репозиторий GitHub из GitHub, нажав кнопку «Продолжить «в разделе «Импорт репозитория Git «.
Импорт проекта Git в Vercel: шаг 1
Далее нам нужно ввести ссылку на наш проект GitHub и нажать кнопку «Продолжить «, чтобы развернуть наше приложение.
Импорт проекта Git в Vercel: шаг 2
Чтобы наше приложение React могло взаимодействовать с нашей серверной частью, нам нужно ввести все переменные среды из нашего.envфайла.
Импорт проекта Git в Vercel: шаг 3
Он должен содержать переменные среды.
Импорт проекта Git в Vercel: шаг 4
Далее мы можем нажать на кнопку Deploy, которая развернет приложение.
Если мы сейчас перейдем по ссылке развертывания, мы сможем просмотреть наше развернутое приложение:
Окончательный интерфейс нашего приложения
Вывод
Живая демонстрация нашего приложения развернута на Vercel, а код доступен на GitHub.
Мы не добавляли никакой аутентификации, чтобы уменьшить сложность и длину руководства, но очевидно, что это потребуется любому реальному приложению.
Firebase действительно полезен там, где вы не хотите создавать и поддерживать отдельное серверное приложение или где вам нужны данные в реальном времени, не тратя слишком много времени на разработку своих API.
Я надеюсь, что этот урок поможет вам в ваших будущих проектах. Пожалуйста, не стесняйтесь обращаться с любыми отзывами.