Лучший опыт

Ускоренный запуск системы “Аутентификации + база данных” (React.js и Firebase).

Жизнь коротка, поэтому тратить время на настройку интегрированной системы аутентификации и базы данных  —  непростительная роскошь для разработчиков полного цикла. Если вы принадлежите к их числу, то наверняка мечтаете о возможности сразу же погрузиться в работу над проектом. Вместо этого часами вынуждены изучать документацию и настраивать новую кодовую базу. Но теперь вашим мучениям приходит конец. Это руководство послужит “?
Ускоренный запуск системы “Аутентификации + база данных” (React.js и Firebase)...

Жизнь коротка, поэтому тратить время на настройку интегрированной системы аутентификации и базы данных  —  непростительная роскошь для разработчиков полного цикла. Если вы принадлежите к их числу, то наверняка мечтаете о возможности сразу же погрузиться в работу над проектом. Вместо этого часами вынуждены изучать документацию и настраивать новую кодовую базу. Но теперь вашим мучениям приходит конец.

Это руководство послужит “скоростным лифтом” для реализации ваших идей уже сегодня. Мы разработаем систему полного цикла с использованием React.js на фронтенде (хотя этот процесс аналогичен и для Next.js-приложений) и Firebase на бэкенде. Данный подход обеспечивает обработку всей тяжелой логики и предлагает феноменальный бесплатный уровень как для аутентификации, так и для базы данных Firestore NoSQL. Вы сможете развернуть свои проекты уже сегодня, совершенно бесплатно, не понеся никаких лишних расходов до тех пор, пока не начнете зарабатывать верные деньги!

Часть 1. Инициализация проекта

Начнем с создания проекта React.js с использованием Vite. Это элементарно: все, что вам понадобиться,  —  выполнить следующую команду в терминале.

npm create vite@latest my-fullstack-react-app -- --template react

Теперь можно открыть проект в редакторе кода.

Очередной задачей будет создание следующих файлов:

  1. /firebase.js;
  2. /src/context/AuthContext.jsx;
  3. /.env;
  4. /src/components/Login.jsx;
  5. /src/components/Dashboard.jsx.

1.0. Firebase.js

Файл firebase.js может содержать следующий код:

import {initializeApp} from 'firebase/app'
import {getAuth} from 'firebase/auth'
import {getFirestore} from 'firebase/firestore'

// Конфигурация Firebase вашего веб-приложения
const firebaseConfig = {
apiKey: import.meta.env.VITE_APIKEY,
authDomain: import.meta.env.VITE_AUTHDOMAIN,
projectId: import.meta.env.VITE_PROJECTID,
storageBucket: import.meta.env.VITE_STORAGEBUCKET,
messagingSenderId: import.meta.env.VITE_MESSAGINGSENDERID,
appId: import.meta.env.VITE_APPID
};

// Инициализация Firebase
const app = initializeApp(firebaseConfig);

export const auth = getAuth(app)
export const db = getFirestore(app)

Этот код инициализирует Firebase в кодовой базе React.js. Кроме того, он инициирует, а затем экспортирует аутентификацию и базу данных Firebase, чтобы к ним можно было получить доступ в других местах проекта.

2.0. AuthContext.jsx

Компонент AuthContext.jsx немного сложнее:

import React, { useContext, useState, useEffect } from 'react'
import { auth, db } from '../../firebase'
import { signInWithEmailAndPassword, createUserWithEmailAndPassword, signOut, onAuthStateChanged } from 'firebase/auth'

const AuthContext = React.createContext()

export function useAuth() {
// Создание хука useAuth для доступа к контексту во всем приложении
return useContext(AuthContext)
}

export function AuthProvider({ children }) {
// Создаем компонент-обертку auth для приложения.
// Можем опционально определить состояние userData и добавить в контекст.
const [currentUser, setCurrentUser] = useState(null)


function signup(email, password) {
return createUserWithEmailAndPassword(auth, email, password)
}

function login(email, password) {
return signInWithEmailAndPassword(auth, email, password)
}

function logout() {
return signOut(auth)
}

useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, user => {
// Здесь можно получить общие данные о пользователях из Firebase
setCurrentUser(user)
})
return unsubscribe
}, [])

const value = {
currentUser,
signup,
logout,
login
}

return (
<AuthContext.Provider value={value}>
{children}
</AuthContext.Provider>
)
}

Этот компонент обладает двумя функциями: первая  —  создание хука useAuth, используемого для доступа к состоянию аутентификации в приложении; вторая  —  создание компонента-обертки (auth wrapper component), необходимого для инкапсулирования всего приложения.

Определяем также логику, которая отслеживает состояние аутентификации, чтобы приложение реагировало на различные состояния аутентификации пользователей. Для демонстрации основных методов аутентификации определены три функции, однако можно создать и другие. Наконец, передаем состояние аутентификации и методы в качестве контекста всему приложению, что позволяет обращаться к ним из любого компонента.

Состояние входа пользователя в систему предусмотрительно сохраняется в куках (cookies). Поэтому, даже при обновлении страницы, состояние аутентификации будет сохраняться в течение определенного периода времени без необходимости повторного входа пользователя.

3.0. Переменные окружения

Чтобы обеспечить безопасность приложения, сохраняем ключи в файле .env. Этот файл можно инициализировать следующим образом:

VITE_APIKEY=
VITE_AUTHDOMAIN=
VITE_PROJECTID=
VITE_STORAGEBUCKET=
VITE_MESSAGINGSENDERID=
VITE_APPID=

Немного позже заполним фактические значения ключей, которые затем будут доступны в файле firebase.js.

4.0. Login.jsx

Теперь нужно инициализировать компонент Login для обработки функций sign-in (входа пользователя) и sign-up (регистрации):

import React, { useState } from 'react'
import { useAuth } from '../context/AuthContext'

export default function Login() {
const [createAccount, setCreateAccount] = useState(false)
const [userCreds, setUserCreds] = useState({ email: '', password: '' })

const { signUp, login } = useAuth()

function updateEmail(e) {
setUserCreds({ ...userCreds, email: e.target.value })
}

function updatePassword(e) {
setUserCreds({ ...userCreds, password: e.target.value })
}

function handleSubmit(e) {
e.preventDefault()
// предотвращает регистрацию, если форма не заполнена
if (!userCreds.email || !userCreds.password) { return }

if (createAccount) {
// рекомендуется добавить сюда проверку пароля с помощью регулярного выражения
console.log('Registering')
signUp(userCreds.email, userCreds.password)
} else {
console.log('Logging in')
login(userCreds.email, userCreds.password)
}
}

return (
<div>
<input placeholder='Email' value={userCreds.email} onChange={(e) => {
updateEmail(e)
}}></input>
<input placeholder='Password' type='password' value={userCreds.password} onChange={(e) => {
updatePassword(e)
}}></input>
<button onClick={handleSubmit}>
<p>Submit</p>
</button>
<button onClick={() => setCreateAccount(!createAccount)}>
<p>{createAccount ? 'Sign In' : 'Sign Up'}</p>
</button>
</div>
)
}

И мы ловко получаем доступ к обоим методам, вызывая хук useContext() и деструктурируя методы изнутри! В JSX-коде компонента создаем два поля ввода для электронной почты и пароля соответственно, кнопку для отправки формы и кнопку для переключения между состояниями регистрации и входа.

5.0. Dashboard.jsx

Наконец, можно отобразить компонент Dashboard для всех, кто вошел в систему.

import React from 'react'
import { doc, increment, serverTimestamp, setDoc } from "firebase/firestore";
import { useAuth } from '../context/AuthContext'
import { db } from '../../firebase';

export default function Dashboard() {
const { logout, currentUser } = useAuth()

async function handleIncrement() {
const userRef = doc(db, 'users', currentUser.uid);
await setDoc(userRef, { counter: increment(1), timestamp: serverTimestamp() }, { merge: true });
}

return (
<div>
<p> hello world & welcome to the dashboard</p>
<button onClick={handleIncrement}>Increment database</button>
<button onClick={logout}>Logout</button>
</div>
)
}

В компоненте Dashboard есть инкрементный счетчик, показывающий, как можно изменять в базе данных информацию, относящуюся к конкретному пользователю, определяя ее через идентификатор пользователя. Кроме того, он содержит функцию logout (выхода из системы) на случай, если пользователь хочет выйти из своего аккаунта.

Подробнее о CRUD-операциях с Firebase/Firestore можно прочитать здесь.

Часть 2. Модификация App.jsx

После создания всех компонентов и файлов остается внести изменения в компонент app.jsx, чтобы он отображал компоненты Login (для неаутентифицированных пользователей) и Dashboard (для тех, кто уже вошел в систему).

import { useAuth } from './context/AuthContext'
import Login from './components/Login'
import Dashboard from './components/Dashboard'

function App() {
const { currentUser } = useAuth()
return (
<div>
{currentUser ? (
<Dashboard />
) : (
<Login />
)}
</div>
)
}

export default App

Этот очень простой компонент приложения получает доступ к состоянию CurrentUser с помощью AuthContext и условно отображает компоненты Dashboard или Login в зависимости от того, найден пользователь или нет.

Часть 3. Инициализация Firebase

Наконец, пришло время использовать ресурсы Firebase для управления аутентификацией и базой данных в облаке (заметим, что это бесплатно при довольно солидном объеме использования).

Перейдем по ссылке и нажмем Get Started, чтобы попасть в консоль разработчика.

Здесь нажмем Add Project, назовем проект, опционально можно подключить Google Analytics. Наконец, попадаем на дэшборд нового проекта! Он должен выглядеть следующим образом:

Дэшборд Firebase-проекта

Теперь можете завершить настройку, выполнив следующие шаги.

1. Выберите Authentication (Аутентификация).

2. На следующей странице нажмите Get Started (Начать).

3. Выберите Email/Password, чтобы включить аутентификацию с помощью электронной почты и пароля.

4. Активируйте Email/Password и нажмите Save (Сохранить).

Этого достаточно для настройки аутентификации в Firebase. Теперь перейдем к инициализации базы данных!

5. Выберите Cloud Firestore, вернувшись на главную страницу.

6. Создайте базу данных. Единственное, что вам нужно учесть, чтобы не беспокоиться о задержках,  —  это местоположение базы данных. Затем нажмите Next (Далее).

7. Переведите базу данных в Test Mode (тестовый режим), чтобы обеспечить доступность опций чтения и записи.

8. Вернитесь к дэшборду, чтобы настроить проект Firebase для веб-приложения. Выберите веб-опцию.

9. Создайте имя приложения и нажмите Register app (зарегистрировать приложение).

10. Вы попадете на экран конфигурации, где будут представлены все ценные ключи, которые нужно вставить в файл .env в кодовой базе React.

Часть 4. Обновление файла .env

Теперь, получив доступ к ключам, необходимым для проекта, можете ввести их в файл .env, чтобы он выглядел следующим образом:

VITE_APIKEY=AIzaSyA3uUJXfR1241241KvUZWi3QnuUel3Y_euSnyg
VITE_AUTHDOMAIN=test123–22ba3.firebaseapp.com
VITE_PROJECTID=test123–22ba3
VITE_STORAGEBUCKET=test123–22ba3.appspot.com
VITE_MESSAGINGSENDERID=176123123817312
VITE_APPID=1:176123123817312:web:89asdklj8123klj8asdf6623c4ffc5

Теперь для всех посторонних лиц проект будет недоступен, что сделает эти ключи недействительными.

Часть 5. Запуск приложения

Проект готов к работе. Можете запустить приложение с помощью следующей команды в терминале:

npm run dev

И загрузите его на http://localhost:5173.

Оттуда вы сможете зарегистрироваться и, войдя в систему, нажать кнопку “Increment” (“Увеличить). Чтобы убедиться в работе приложения, посмотрите на консоль Firestore с главной страницы Firebase  —  вы увидите, что пользовательские данные увеличились вместе с временной меткой.

Вот и все! Поздравляю с завершением скоростного запуска проекта “Аутентификация и базы данных с помощью React.js + Firebase”. Пусть ваши разработки полного цикла будут безопасными и управляют большим количеством пользовательских данных.