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

Этот процесс оказался проще, чем я ожидал, но также имел несколько «подводных камней», от которых мне пришлось избавляться.

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

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

Документы Firebase и CSS Tricks

Аутентификацию Google довольно просто настроить, потому что Google делает всю тяжелую работу за вас.
Он работает с учетной записью пользователя Google, которая активирована в его браузере. Пока пользователи вошли в Google, они должны просто иметь возможность выбрать свою учетную запись, и им не нужно будет вводить свой пароль.

Когда пользователь вошел только в одну учетную запись Google в своем браузере, ему будет предложено выбрать, какую учетную запись они хотят использовать при первом входе в систему. С этого момента они могут входить и выходить без ввода какой-либо информации. Логин для вашего приложения теперь связан с учетными данными их браузера.

Если пользователь вошел в несколько учетных записей Google в своем браузере, «войти в систему» ​​позволит ему выбрать, какую учетную запись Google использовать при каждом входе в систему.

Чтобы начать аутентификацию, выполните несколько шагов в своей учетной записи Firebase.

Сначала нам нужно добавить аутентификацию в наше приложение Firebase. На боковой панели «Разработка» выберите вкладку аутентификации. Затем выберите вкладку «Метод входа» и включите Google.

Нам также необходимо обновить правила для нашей базы данных, чтобы они читались и записывались только для зарегистрированных пользователей. Перейдите на вкладку «База данных» и выберите вкладку «Правила».

//Replace your rules with these ones.
{
 “rules”: {
 “.read”: “auth != null”,
 “.write”: “auth != null”
 }
}

В вашем приложении React нам сначала нужно убедиться, что мы правильно импортируем Firebase.
Если вы импортируете весь Firebase, вы должны установить. Однако может быть лучше просто добавить те части Firebase, которые вы хотите использовать. Вот как выглядит мой файл настройки Firebase.
Примечание: ваша конфигурация Firebase находится в настройках вашей учетной записи Firebase. Каждый из ваших ключей будет иметь значения, характерные для вашего проекта (не пустые, как в этом примере).

import firebase from ‘firebase/app’;
import ‘firebase/database’;
import ‘firebase/auth’;
// Your web app’s Firebase configuration
const firebaseConfig = {
 apiKey: “”,
 authDomain: “”,
 databaseURL: “”,
 projectId: “”,
 storageBucket: “”,
 messagingSenderId: “”,
 appId: “”
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
export default firebase;

Круто, значит, вы правильно установили Firebase, настроили свой проект в Firebase и настроили в компоненте firebase.js. Вы не забыли импортировать firebase.js в App.js или любой другой компонент, над которым вы работаете, которому это нужно?

Теперь, когда это не так, необходимо настроить авторизацию еще кое-что, прежде чем мы начнем писать функции и т. д.

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

const provider = new firebase.auth.GoogleAuthProvider();
const auth = firebase.auth()

Следующий шаг — добавить несколько вещей в состояние (внутри суперконструктора и this.state= {}). user — это место, где мы собираемся хранить данные, чтобы проверить, вошел ли пользователь в систему. userID будет содержать уникальный идентификатор Google, связанный с каждой учетной записью Google.

user: null,
userID: “”

Далее нам нужно написать несколько функций для входа и выхода.

Для входа в систему мы получаем доступ к функции аутентификации Firebase (которая сделает вход в Google всплывающим).

Затем нам нужно установить состояние пользователя. result.user возвращает объект user. Сохранение этого в состоянии как user изменит это значение с нуля и сделает значение «истинным», которое будет использоваться для определения, вошел ли пользователь в систему.
В то же время мы собираемся установить состояние userID. user возвращает объект, поэтому мы собираемся получить доступ к uid (идентификатору пользователя) ключу и сохранить значение в получить только уникальную строку для каждого пользователя в состоянии.

login = () => {
  auth.signInWithPopup(provider)
    .then((result) => {
      const user = result.user;
      this.setState({
        user,
        userID: user.uid
      });
     });
}

Функция выхода из системы проста, она просто возвращает состояние пользователя к нулю.

logout = () => {
  auth.signOut()
   .then(() => {
     this.setState({
       user: null
     });
   });
}

Время использовать эти функции!

Мы собираемся условно отображать кнопку входа или выхода на экран в зависимости от того, является ли состояние пользователя нулевым или нет. Затем каждая кнопка получает соответствующую функцию onClick. Прикрепите это где-нибудь в вашем возврате рендеринга, что вы хотите, чтобы кнопка была на странице. Предлагаю заголовок.

{this.state.user ? <button onClick={this.logout}>Log Out</button> : <button onClick={this.login}>Log In</button>}

Теперь пользователь может войти или выйти из системы! Вот так просто, да? Чтобы на самом деле использовать тот факт, что у нашего пользователя есть учетная запись, нам нужно сделать еще несколько вещей.

  • Отправьте уникальные данные в Firebase для сохранения.
  • Верните эти данные для пользователя, когда он войдет в систему, и его сеанс сохранится (то есть не выходите из него при каждом обновлении страницы).

Я не буду вдаваться в подробности о том, как передавать (устанавливать или обновлять) данные в Firebase, но для создания данных нового пользователя в Firebase вам нужно сделать один шаг по-другому.

Обычно, если вы пишете функцию для отправки информации в Firebase, вы должны сохранить функцию/путь dbRef в переменной, а затем

const dbRef = firebase.database().ref()

или, может быть, если вам нужно несколько объектов в вашей Firebase, вы бы установили путь,

const dbRef = firebase.database().ref(“object-name”)

затем вы должны нажать (или установить или обновить) эти данные.

dbRef.push({
  data1: this.state.something
})

Чтобы сохранить уникальные пользовательские данные, вам нужно сохранить уникальные пути. Вы можете сделать это с литералом шаблона в вашем ref(). Сначала назовите объект, в котором вы будете хранить своих пользователей (в данном примере «пользователи»), а затем идентификатор пользователя, который у вас есть в состоянии.

const dbRef = firebase.database().ref(`users/${this.state.userID}`)

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

const dbRef = firebase.database().ref(`users/${this.state.userID}/goals`)

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

Оказывается, проблема возникла из-за того, как я нажимал и извлекал из Firebase. Через мгновение я перейду к извлечению данных из вашего componentDidMount, а пока поймите, что когда компонент монтировался, я просил извлечь все различные биты данных (в моем случае объект, названный целями, с двумя значения и объект с именем tracker, который содержит массив массивов) из моей Firebase для этого пользователя.

Однако новый пользователь только отправил свои «цели» в Firebase, а затем страница пыталась смонтировать как «цели», так и «трекер» для этого пользователя. Но «трекера» еще не было, поэтому страница вылетала.

Я решил эту проблему, убедившись, что в функции, устанавливающей «цель» пользователя, я также добавил пустую версию «трекера».

const dbRef = firebase.database().ref(this.props.user ? `users/${this.props.userID}/goal` : `goal`);
 dbRef.set({
    number: this.props.goalState,
    activity: this.props.goalString
 });
firebase.database().ref(this.props.user ? `users/${this.props.userID}/tracker` : `tracker`);
 dbRef.update({
    tracker: [[0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0,      0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]],
 });

Это было «исправление», но означало, что данные пользователя удалялись всякий раз, когда они ставили цель. Я решил, что это будет работать на данный момент, поскольку пользователь, скорее всего, обновит свою цель только в том случае, если он установит новую.

Вот как это выглядело в Firebase.

С тех пор я подумал о другом решении, которое можно было бы использовать в componentDidMount, но еще не тестировал. Возможно, условный оператор, спрашивающий, существует ли «трекер», и удаляющий его только в том случае, если он существует, также решил бы эту проблему.

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

Мы собираемся написать код в нашем componentDidMount. Сначала нам нужна функция, которая проверяет, вошел ли пользователь в систему. Это может занять некоторое время, чтобы установить состояние, поэтому нам нужно запустить зависимый код в функции обратного вызова.

auth.onAuthStateChanged((user) => {
  if (user) {
   this.setState({
    user,
    userID: user.uid
}

Затем вам нужно прикрепить функцию обратного звонка на этот

 () => {next function goes here}

Возьмите объект, связанный с вашим пользователем, из Firebase.

const dbRef = firebase.database().ref(`users/${this.state.userID}`)

Затем возьмите значение этих данных и обновите с его помощью свои состояния.

dbRef.on(‘value’, (data) => {
const dataBase = data.val();
  //then update your state to match the things you saved here
}

Ты сделал это! Теперь ваши пользователи могут входить и выходить из системы, а вы можете сохранять и возвращать их данные!