In diesem Artikel behandeln wir Schlüsselkonzepte zur Authentifizierung eines Benutzers mit Firebase in einer Echtzeit-Chat-Anwendung. Wir werden Drittanbieter-Authentifizierungsanbieter (z. B. Google, Twitter und GitHub) integrieren und, sobald sich Benutzer angemeldet haben, lernen, wie wir Benutzer-Chatdaten in der Firebase Realtime Database speichern können, wo wir Daten mit einer NoSQL-Cloud-Datenbank synchronisieren können.
Die Client-Anwendung wird in React erstellt, da es eines der beliebtesten JavaScript-Frameworks ist. Die Konzepte können jedoch auch auf andere Frameworks angewendet werden.
Aber zuerst: Was ist Firebase?
Firebase ist Googles mobile Plattform zur schnellen Entwicklung von Apps. Firebase bietet eine Reihe von Tools zur Authentifizierung von Anwendungen, zum Erstellen reaktiver Client-Apps, zur Analyse von Berichten sowie eine Vielzahl weiterer hilfreicher Ressourcen zur allgemeinen Verwaltung von Apps. Es bietet auch Back-End-Management für Web, iOS, Android und Unity, eine 3D-Entwicklungsplattform.
Standardmäßig ist Firebase mit Funktionen ausgestattet, die Entwicklern wie uns helfen, sich auf die Entwicklung von Apps zu konzentrieren, während es die gesamte serverseitige Logik übernimmt. Dinge wie
- Authentifizierung: Dies beinhaltet die Unterstützung für E-Mail- und Passwort-Authentifizierung sowie Single-Sign-On-Funktionen (über Facebook, Twitter und Google).
- Echtzeitdatenbank: Dies ist eine "NoSQL"-Datenbank, die sich in Echtzeit aktualisiert.
- Cloud-Funktionen: Diese führen zusätzliche serverseitige Logik aus.
- Statische Hosting: Dies ist ein Mittel, um vorab erstellte Assets bereitzustellen, anstatt sie zur Laufzeit zu rendern.
- Cloud Storage: Dies bietet uns einen Ort zur Speicherung von Medieninhalten.
Firebase bietet einen großzügigen kostenlosen Tarif, der Authentifizierung und Zugriff auf seine Realtime Database beinhaltet. Die Authentifizierungsanbieter, die wir behandeln werden – E-Mail und Passwort sowie Google und GitHub – sind auf dieser Seite ebenfalls kostenlos. Die Realtime Database erlaubt bis zu 100 gleichzeitige Verbindungen und 1 Gigabyte Speicher pro Monat. Eine vollständige Preisübersicht finden Sie auf der Firebase-Website.
Das erstellen wir
Wir werden eine Anwendung namens Chatty erstellen. Sie wird es nur authentifizierten Benutzern ermöglichen, Nachrichten zu senden und zu lesen, und Benutzer können sich registrieren, indem sie ihre E-Mail-Adresse angeben und ein Passwort erstellen, oder indem sie sich über ein Google- oder GitHub-Konto authentifizieren. Schauen Sie sich den Quellcode an, wenn Sie ihn referenzieren möchten oder einen Blick darauf werfen möchten, während wir beginnen.
Am Ende werden wir etwas Ähnliches wie dies haben
Einrichtung
Sie benötigen ein Google-Konto, um Firebase nutzen zu können. Besorgen Sie sich also eines, falls Sie noch keines haben. Und sobald Sie das getan haben, können wir offiziell mit diesem Ding loslegen.
Gehen Sie zuerst zur Firebase Console und klicken Sie auf die Option „Projekt hinzufügen“.

Geben Sie als Nächstes einen Namen für das Projekt ein. Ich wähle Chatty.

Sie können Ihrem Projekt Analysen hinzufügen, aber es ist nicht erforderlich. Klicken Sie in jedem Fall auf „Weiter“, um fortzufahren, und Firebase benötigt einige Sekunden, um Ressourcen für das Projekt zuzuweisen.

Sobald dies hochgefahren ist, gelangen wir zum Firebase-Dashboard. Bevor wir Firebase jedoch in unserer Web-App verwenden können, müssen wir die Konfigurationsdetails für unser Projekt festhalten. Klicken Sie also auf das Websymbol im Dashboard.

Geben Sie dann einen Namen für die App ein und klicken Sie auf App registrieren.

Als Nächstes kopieren wir die Konfigurationsdetails auf dem nächsten Bildschirm und speichern sie an einem sicheren Ort. Das wird im nächsten Schritt nützlich sein.

Auch hier werden wir Benutzer über E-Mail und Passwort authentifizieren, mit zusätzlichen Optionen für Single-Sign-On mit einem Google- oder GitHub-Konto. Wir müssen diese über den Authentifizierungs-Tab im Dashboard aktivieren, aber wir werden jeden einzelnen nacheinander durchgehen.

E-Mail- und Passwort-Authentifizierung
Im Firebase-Dashboard gibt es einen Tab namens Anmeldemethode. Klicken Sie auf die Option E-Mail/Passwort und aktivieren Sie sie.


Jetzt können wir es in unserer App verwenden!
Einrichtung der Web-App
Für unsere Web-App werden wir React verwenden, aber die meisten Konzepte können auf jedes andere Framework angewendet werden. Wir benötigen Node.js für eine React-Einrichtung, also laden Sie es herunter und installieren Sie es, falls Sie das noch nicht getan haben.
Wir werden create-react-app verwenden, um ein neues React-Projekt zu bootstrappen. Dies lädt die notwendigen Pakete herunter und installiert sie, die für eine React-Anwendung erforderlich sind. Wechseln Sie im Terminal zu dem Verzeichnis, in dem Ihr Chatty-Projekt platziert werden soll, und führen Sie dies aus, um es zu initialisieren
npx create-react-app chatty
Dieser Befehl führt die Erstkonfiguration für unsere React-App durch und installiert die Abhängigkeiten in package.json. Wir werden auch einige zusätzliche Pakete installieren. Wechseln wir also in das Projekt selbst und fügen wir Pakete für React Router und Firebase hinzu.
cd chatty
yarn add react-router-dom firebase
Wir wissen bereits, warum wir Firebase brauchen, aber warum React Router? Unsere Chat-App wird ein paar Ansichten haben, wir können React Router verwenden, um die Navigation zwischen Seiten zu handhaben.
Damit ist das erledigt, wir können die App offiziell starten
yarn start
Dies startet einen Entwicklungsserver und öffnet eine URL in Ihrem Standardbrowser. Wenn alles korrekt installiert wurde, sollten Sie einen Bildschirm wie diesen sehen

Wenn Sie sich die Ordnerstruktur ansehen, würden Sie etwas Ähnliches wie dieses sehen

Für unsere Chat-App werden wir diese Ordnerstruktur verwenden

/components: enthält wiederverwendbare Widgets, die auf verschiedenen Seiten verwendet werden/helpers: ein Satz wiederverwendbarer Funktionen/pages: die App-Ansichten/services: Drittanbieterdienste, die wir verwenden (z. B. Firebase)App.js: die Root-Komponente
Alles andere im Ordner ist für dieses Projekt unnötig und kann sicher entfernt werden. Von hier aus fügen wir Code zu src/services/firebase.js hinzu, damit die App mit Firebase kommunizieren kann.
import firebase from 'firebase';
Holen wir Firebase in die App
Wir werden Firebase mit den Konfigurationsdetails, die wir zuvor bei der Registrierung der App im Firebase-Dashboard kopiert haben, importieren und initialisieren. Dann werden wir die Authentifizierungs- und Datenbankmodule exportieren.
const config = {
apiKey: "ADD-YOUR-DETAILS-HERE",
authDomain: "ADD-YOUR-DETAILS-HERE",
databaseURL: "ADD-YOUR-DETAILS-HERE"
};
firebase.initializeApp(config);
export const auth = firebase.auth;
export const db = firebase.database();
Importieren wir unsere Abhängigkeiten in src/App.js
import React, { Component } from 'react';
import {
Route,
BrowserRouter as Router,
Switch,
Redirect,
} from "react-router-dom";
import Home from './pages/Home';
import Chat from './pages/Chat';
import Signup from './pages/Signup';
import Login from './pages/Login';
import { auth } from './services/firebase';
Dies sind ES6-Importe. Speziell importieren wir React und andere Pakete, die zum Aufbau der App benötigt werden. Wir importieren auch alle Seiten unserer App, die wir später für unseren Router konfigurieren werden.
Als Nächstes kommt das Routing
Unsere App hat öffentliche Routen (zugänglich ohne Authentifizierung) und eine private Route (nur mit Authentifizierung zugänglich). Da React keine Möglichkeit bietet, den authentifizierten Status zu überprüfen, werden wir Higher-Order Components (HOCs) für beide Routentypen erstellen.
Unsere HOCs werden
- einen
<Route>umschließen, - Props vom Router an die
<Route>weitergeben, - die Komponente basierend auf dem Authentifizierungsstatus rendern, und
- den Benutzer zu einer angegebenen Route weiterleiten, wenn die Bedingung nicht erfüllt ist
Schreiben wir den Code für unser <PrivateRoute> HOC.
function PrivateRoute({ component: Component, authenticated, ...rest }) {
return (
<Route
{...rest}
render={(props) => authenticated === true
? <Component {...props} />
: <Redirect to={{ pathname: '/login', state: { from: props.location } }} />}
/>
)
}
Es empfängt drei Props: die zu rendernde Komponente, wenn die Bedingung wahr ist, den authenticated-Status und den ES6-Spread-Operator, um die restlichen Parameter zu erhalten, die vom Router übergeben werden. Es prüft, ob authenticated wahr ist und rendert die übergebene Komponente, andernfalls wird zu /login weitergeleitet.
function PublicRoute({ component: Component, authenticated, ...rest }) {
return (
<Route
{...rest}
render={(props) => authenticated === false
? <Component {...props} />
: <Redirect to='/chat' />}
/>
)
}
Die <PublicRoute> ist praktisch identisch. Sie rendert unsere öffentlichen Routen und leitet zum Pfad /chat weiter, wenn der Authentifizierungsstatus wahr wird. Wir können die HOCs in unserer Render-Methode verwenden
render() {
return this.state.loading === true ? <h2>Loading...</h2> : (
<Router>
<Switch>
<Route exact path="/" component={Home}></Route>
<PrivateRoute path="/chat" authenticated={this.state.authenticated} component={Chat}></PrivateRoute>
<PublicRoute path="/signup" authenticated={this.state.authenticated} component={Signup}></PublicRoute>
<PublicRoute path="/login" authenticated={this.state.authenticated} component={Login}></PublicRoute>
</Switch>
</Router>
);
}
Prüfung auf Authentifizierung
Es wäre gut, eine Ladeanzeige anzuzeigen, während wir überprüfen, ob der Benutzer authentifiziert ist. Sobald die Prüfung abgeschlossen ist, rendern wir die entsprechende Route, die der URL entspricht. Wir haben drei öffentliche Routen – <Home>, <Login> und <Signup> – und eine private namens <Chat>.
Schreiben wir die Logik, um zu prüfen, ob der Benutzer tatsächlich authentifiziert ist.
class App extends Component {
constructor() {
super();
this.state = {
authenticated: false,
loading: true,
};
}
}
export default App;
Hier setzen wir den anfänglichen Zustand der App. Dann verwenden wir den componentDidMount Lifecycle Hook, um zu prüfen, ob der Benutzer authentifiziert ist. Fügen wir dies also nach dem Konstruktor hinzu
componentDidMount() {
auth().onAuthStateChanged((user) => {
if (user) {
this.setState({
authenticated: true,
loading: false,
});
} else {
this.setState({
authenticated: false,
loading: false,
});
}
})
}
Firebase stellt eine intuitive Methode namens onAuthStateChanged bereit, die ausgelöst wird, wenn sich der Authentifizierungsstatus ändert. Wir verwenden diese, um unseren anfänglichen Zustand zu aktualisieren. user ist null, wenn der Benutzer nicht authentifiziert ist. Wenn user wahr ist, aktualisieren wir authenticated auf true; andernfalls setzen wir es auf false. Wir setzen auch loading auf false, egal was passiert.
Benutzer mit E-Mail und Passwort registrieren
Benutzer können sich bei Chatty per E-Mail und Passwort registrieren. Der Ordner helpers enthält eine Reihe von Methoden, die wir zur Handhabung einiger Authentifizierungslogik verwenden werden. Erstellen Sie in diesem Ordner eine neue Datei namens auth.js und fügen Sie dies hinzu
import { auth } from "../services/firebase";
Wir importieren das Authentifizierungsmodul aus dem zuvor erstellten Dienst.
export function signup(email, password) {
return auth().createUserWithEmailAndPassword(email, password);
}
export function signin(email, password) {
return auth().signInWithEmailAndPassword(email, password);
}
Wir haben hier zwei Methoden: signup und signin
signuperstellt einen neuen Benutzer anhand seiner E-Mail-Adresse und seines Passworts.signinmeldet einen bestehenden Benutzer an, der mit E-Mail und Passwort erstellt wurde.
Erstellen wir unsere <Signup>-Seite, indem wir eine neue Datei Signup.js im Seitenordner erstellen. Dies ist das Markup für die Benutzeroberfläche
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { signup } from '../helpers/auth';
export default class SignUp extends Component {
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<h1>
Sign Up to
<Link to="/">Chatty</Link>
</h1>
<p>Fill in the form below to create an account.</p>
<div>
<input placeholder="Email" name="email" type="email" onChange={this.handleChange} value={this.state.email}></input>
</div>
<div>
<input placeholder="Password" name="password" onChange={this.handleChange} value={this.state.password} type="password"></input>
</div>
<div>
{this.state.error ? <p>{this.state.error}</p> : null}
<button type="submit">Sign up</button>
</div>
<hr></hr>
<p>Already have an account? <Link to="/login">Login</Link></p>
</form>
</div>
)
}
}

Das Formular und die Eingabefelder sind an eine Methode gebunden, die wir noch nicht erstellt haben. Sortieren wir das also aus. Kurz vor der render()-Methode fügen wir Folgendes hinzu
constructor(props) {
super(props);
this.state = {
error: null,
email: '',
password: '',
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
Wir setzen den anfänglichen Zustand der Seite. Wir binden auch die Methoden handleChange und handleSubmit an den Gültigkeitsbereich des `this`-Objekts der Komponente.
handleChange(event) {
this.setState({
[event.target.name]: event.target.value
});
}
Als Nächstes fügen wir die Methode handleChange hinzu, an die unsere Eingabefelder gebunden sind. Die Methode verwendet berechnete Eigenschaften, um den Schlüssel dynamisch zu bestimmen und die entsprechende Zustandsvariable festzulegen.
async handleSubmit(event) {
event.preventDefault();
this.setState({ error: '' });
try {
await signup(this.state.email, this.state.password);
} catch (error) {
this.setState({ error: error.message });
}
}
Bei handleSubmit verhindern wir das Standardverhalten von Formularübermittlungen (das unter anderem den Browser neu lädt). Wir bereinigen die Fehlersatzvariable und verwenden dann die aus helpers/auth importierte signup()-Methode, um die vom Benutzer eingegebene E-Mail und das Passwort zu übergeben.
Wenn die Registrierung erfolgreich ist, werden die Benutzer zur Route /Chats weitergeleitet. Dies ist möglich durch die Kombination von onAuthStateChanged und den zuvor erstellten HOCs. Wenn die Registrierung fehlschlägt, setzen wir die Fehlervariable, die dem Benutzer eine Nachricht anzeigt.
Benutzer mit E-Mail und Passwort authentifizieren
Die Login-Seite ist identisch mit der Signup-Seite. Der einzige Unterschied ist, dass wir die signin-Methode aus den zuvor erstellten Hilfsmitteln verwenden werden. Erstellen wir also eine weitere neue Datei im Seitenverzeichnis, diesmal mit dem Namen Login.js, und fügen Sie diesen Code hinzu
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { signin, signInWithGoogle, signInWithGitHub } from "../helpers/auth";
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
email: "",
password: ""
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({
[event.target.name]: event.target.value
});
}
async handleSubmit(event) {
event.preventDefault();
this.setState({ error: "" });
try {
await signin(this.state.email, this.state.password);
} catch (error) {
this.setState({ error: error.message });
}
}
render() {
return (
<div>
<form
autoComplete="off"
onSubmit={this.handleSubmit}
>
<h1>
Login to
<Link to="/">
Chatty
</Link>
</h1>
<p>
Fill in the form below to login to your account.
</p>
<div>
<input
placeholder="Email"
name="email"
type="email"
onChange={this.handleChange}
value={this.state.email}
/>
</div>
<div>
<input
placeholder="Password"
name="password"
onChange={this.handleChange}
value={this.state.password}
type="password"
/>
</div>
<div>
{this.state.error ? (
<p>{this.state.error}</p>
) : null}
<button type="submit">Login</button>
</div>
<hr />
<p>
Don't have an account? <Link to="/signup">Sign up</Link>
</p>
</form>
</div>
);
}
}
Wiederum sehr ähnlich wie zuvor. Wenn sich der Benutzer erfolgreich anmeldet, wird er zu /chat weitergeleitet.
Authentifizierung mit einem Google-Konto
Firebase ermöglicht es uns, Benutzer mit einem gültigen Google-Konto zu authentifizieren. Wir müssen es im Firebase-Dashboard aktivieren, genau wie wir es für E-Mail und Passwort getan haben.

Auf derselben Seite müssen wir auch nach unten scrollen, um eine Domain zur Liste der Domains hinzuzufügen, die zur Funktion berechtigt sind. Auf diese Weise vermeiden wir Spam von jeder Domain, die nicht auf der Whitelist steht. Zu Entwicklungszwecken ist unsere Domain localhost, also bleiben wir vorerst dabei.

Wir können jetzt zurück zu unserem Editor wechseln. Wir werden eine neue Methode zu helpers/auth.js hinzufügen, um die Google-Authentifizierung zu handhaben.
export function signInWithGoogle() {
const provider = new auth.GoogleAuthProvider();
return auth().signInWithPopup(provider);
}
Hier erstellen wir eine Instanz von GoogleAuthProvider. Dann rufen wir signInWithPopup mit dem Anbieter als Parameter auf. Wenn diese Methode aufgerufen wird, erscheint ein Popup, das den Benutzer durch den Google-Anmeldevorgang führt, bevor er zur App zurückgeleitet wird. Sie haben das wahrscheinlich schon einmal selbst erlebt.

Verwenden wir es auf unserer Signup-Seite, indem wir die Methode importieren
import { signin, signInWithGoogle } from "../helpers/auth";
Fügen wir dann einen Button hinzu, um die Methode auszulösen, direkt unter dem Button Registrieren
<p>Or</p>
<button onClick={this.googleSignIn} type="button">
Sign up with Google
</button>
Als Nächstes fügen wir den onClick-Handler hinzu
async googleSignIn() {
try {
await signInWithGoogle();
} catch (error) {
this.setState({ error: error.message });
}
}
Oh, und wir sollten nicht vergessen, den Handler an die Komponente zu binden
constructor() {
// ...
this.githubSignIn = this.githubSignIn.bind(this);
}
Das ist alles, was wir brauchen! Wenn der Button geklickt wird, führt er die Benutzer durch den Google-Anmeldevorgang und, wenn erfolgreich, leitet die App den Benutzer zur Chat-Route weiter.
Authentifizierung mit einem GitHub-Konto
Das Gleiche machen wir auch mit GitHub. Geben wir den Leuten ruhig mehr als eine Auswahl an Konten.
Lassen Sie uns die Schritte durchgehen. Zuerst aktivieren wir die GitHub-Anmeldung im Firebase-Dashboard, genau wie bei E-Mail und Google.

Sie werden feststellen, dass sowohl die Felder Client-ID als auch Client-Secret leer sind, aber wir haben unsere autorisierte Callback-URL unten. Kopieren Sie diese, denn wir werden sie verwenden, wenn wir unser nächstes Ding tun, nämlich die App auf GitHub registrieren.

Sobald das erledigt ist, erhalten wir eine Client-ID und ein Secret, die wir nun in die Firebase-Konsole einfügen können.

Wechseln wir zurück zum Editor und fügen eine neue Methode zu helpers/auth.js hinzu
export function signInWithGitHub() {
const provider = new auth.GithubAuthProvider();
return auth().signInWithPopup(provider);
}
Es ist ähnlich wie die Google-Anmeldeschnittstelle, aber diesmal erstellen wir einen GithubAuthProvider. Dann rufen wir signInWithPopup mit dem Anbieter auf.
In pages/Signup.js aktualisieren wir unsere Importe, um die Methode signInWithGitHub aufzunehmen
import { signup, signInWithGoogle, signInWithGitHub } from "../helpers/auth";
Wir fügen einen Button für die GitHub-Anmeldung hinzu
<button type="button" onClick={this.githubSignIn}>
Sign up with GitHub
</button>
Dann fügen wir einen Klick-Handler für den Button hinzu, der den GitHub-Anmeldevorgang auslöst
async githubSignIn() {
try {
await signInWithGitHub();
} catch (error) {
this.setState({ error: error.message });
}
}
Denken wir auch hier daran, den Handler an die Komponente zu binden
constructor() {
// ...
this.githubSignIn = this.githubSignIn.bind(this);
}
Jetzt erhalten wir denselben Anmelde- und Authentifizierungsvorgang wie bei Google, aber mit GitHub.
Daten aus Firebase lesen
Firebase hat zwei Arten von Datenbanken: Ein Produkt namens Realtime Database und ein anderes namens Cloud Firestore. Beide Datenbanken sind NoSQL-ähnliche Datenbanken, was bedeutet, dass die Datenbank als Schlüssel-Wert-Paare strukturiert ist. Für dieses Tutorial verwenden wir die Realtime Database.

Dies ist die Struktur, die wir für unsere App verwenden werden. Wir haben einen Root-Knoten chats mit Kindknoten. Jedes Kind hat einen Inhalt, einen Zeitstempel und eine Benutzer-ID. Einer der Tabs, den Sie bemerken werden, sind Regeln, mit denen wir Berechtigungen für den Inhalt der Datenbank festlegen.

Firebase-Datenbankregeln werden ebenfalls als Schlüssel-Wert-Paare definiert. Hier legen wir unsere Regeln fest, um nur authentifizierten Benutzern das Lesen und Schreiben in den Chat-Knoten zu gestatten. Es gibt viele weitere Firebase-Regeln, die es wert sind, sie sich anzusehen.
Schreiben wir Code, um aus der Datenbank zu lesen. Erstellen Sie zuerst eine neue Datei namens Chat.js im Seitenordner und fügen Sie diesen Code hinzu, um React, Firebase-Authentifizierung und die Echtzeitdatenbank zu importieren
import React, { Component } from "react";
import { auth } from "../services/firebase";
import { db } from "../services/firebase"
Als Nächstes definieren wir den anfänglichen Zustand der App
export default class Chat extends Component {
constructor(props) {
super(props);
this.state = {
user: auth().currentUser,
chats: [],
content: '',
readError: null,
writeError: null
};
}
async componentDidMount() {
this.setState({ readError: null });
try {
db.ref("chats").on("value", snapshot => {
let chats = [];
snapshot.forEach((snap) => {
chats.push(snap.val());
});
this.setState({ chats });
});
} catch (error) {
this.setState({ readError: error.message });
}
}
}
Die eigentliche Hauptlogik findet in componentDidMount statt. db.ref("chats") ist eine Referenz auf den Chat-Pfad in der Datenbank. Wir lauschen auf das Wert-Ereignis, das jedes Mal ausgelöst wird, wenn ein neuer Wert zum Chat-Knoten hinzugefügt wird. Was aus der Datenbank zurückgegeben wird, ist ein Array-ähnliches Objekt, das wir durchlaufen und jedes Objekt in ein Array pushen. Dann setzen wir die chats-Zustandsvariable auf unser Ergebnis-Array. Wenn ein Fehler auftritt, setzen wir die readError-Zustandsvariable auf die Fehlermeldung.
Eine Sache, die hier zu beachten ist, ist, dass eine Verbindung zwischen dem Client und unserer Firebase-Datenbank hergestellt wird, weil wir die .on()-Methode verwendet haben. Das bedeutet, dass die Client-App jedes Mal, wenn ein neuer Wert zur Datenbank hinzugefügt wird, in Echtzeit aktualisiert wird, was bedeutet, dass Benutzer neue Chats ohne Seitenaktualisierung sehen können. Nett!
Nach componentDidMount können wir unsere Chats wie folgt rendern
render() {
return (
<div>
<div className="chats">
{this.state.chats.map(chat => {
return <p key={chat.timestamp}>{chat.content}</p>
})}
</div>
<div>
Login in as: <strong>{this.state.user.email}</strong>
</div>
</div>
);
}
Dies rendert das Array von Chats. Wir rendern die E-Mail des aktuell angemeldeten Benutzers.
Daten in Firebase schreiben
Derzeit können Benutzer nur aus der Datenbank lesen, sind aber nicht in der Lage, Nachrichten zu senden. Was wir brauchen, ist ein Formular mit einem Eingabefeld, das eine Nachricht akzeptiert, und einer Schaltfläche, um die Nachricht an den Chat zu senden.
Modifizieren wir also das Markup wie folgt
return (
<div>
<div className="chats">
{this.state.chats.map(chat => {
return <p key={chat.timestamp}>{chat.content}</p>
})}
</div>
{# message form #}
<form onSubmit={this.handleSubmit}>
<input onChange={this.handleChange} value={this.state.content}></input>
{this.state.error ? <p>{this.state.writeError}</p> : null}
<button type="submit">Send</button>
</form>
<div>
Login in as: <strong>{this.state.user.email}</strong>
</div>
</div>
);
}
Wir haben ein Formular mit einem Eingabefeld und einer Schaltfläche hinzugefügt. Der Wert des Eingabefeldes ist an unsere Zustandsvariable content gebunden, und wir rufen handleChange auf, wenn sich sein Wert ändert.
handleChange(event) {
this.setState({
content: event.target.value
});
}
handleChange holt den Wert aus dem Eingabefeld und setzt ihn auf unsere Zustandsvariable. Zum Absenden des Formulars rufen wir handleSubmit auf
async handleSubmit(event) {
event.preventDefault();
this.setState({ writeError: null });
try {
await db.ref("chats").push({
content: this.state.content,
timestamp: Date.now(),
uid: this.state.user.uid
});
this.setState({ content: '' });
} catch (error) {
this.setState({ writeError: error.message });
}
}
Wir setzen alle vorherigen Fehler auf null. Wir erstellen eine Referenz auf den chats-Knoten in der Datenbank und verwenden push(), um einen eindeutigen Schlüssel zu erstellen und das Objekt dorthin zu pushen.
Wie immer müssen wir unsere Methoden an die Komponente binden
constructor(props) {
// ...
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
Jetzt kann ein Benutzer neue Nachrichten zu den Chats hinzufügen und sie in Echtzeit sehen! Wie cool ist das?
Demo!
Genießen Sie Ihre neue Chat-App!
Glückwunsch! Sie haben gerade ein Chat-Tool erstellt, das Benutzer mit E-Mail und Passwort authentifiziert, zusammen mit Optionen zur Authentifizierung über ein Google- oder GitHub-Konto.
Ich hoffe, dies gibt Ihnen eine gute Vorstellung davon, wie praktisch Firebase sein kann, um mit der Authentifizierung in einer App loszulegen. Wir haben an einer Chat-App gearbeitet, aber das wahre Juwel sind die Registrierungs- und Anmeldemethoden, die wir entwickelt haben, um darauf zuzugreifen. Das ist für viele Apps nützlich.
Fragen? Gedanken? Feedback? Lassen Sie es mich in den Kommentaren wissen!
Hallo Deven, dieses Beispiel sieht sauber aus, aber es ist eher ein Chatraum. Wie wäre es mit personalisierten Chats, wie spezifische Benutzer & ihre Konversation, gibt es dafür ein Beispiel??
Ja, das ist möglich (habe vor ein paar Jahren eine ähnliche App erstellt), aber im Moment habe ich kein Live-Beispiel oder Tutorial dafür, und dieser Artikel konzentriert sich mehr auf die Authentifizierung. Diese Funktionen liegen außerhalb des Rahmens dieses Artikels – vielleicht schreibe ich in naher Zukunft ein Schritt-für-Schritt-Tutorial dazu.
Wo genau platziert man diese Methoden. Was meinen Sie mit „wir können dies in unserer Render-Methode verwenden“? In welcher Datei? Gibt es ein vollständiges Beispiel auf GitHub?
Hallo Max,
die Render-Methode befindet sich in Ihrer App.js-Datei.
Bitte überprüfen Sie das GitHub-Projekt unter: https://github.com/Dunebook/Firebase-auth-chat-app, hoffentlich hilft Ihnen das weiter!
Schöner Artikel, danke fürs Schreiben. Ich entwickle eine mobile App, die kleine Chats zwischen 3-10 Benutzern als Nebenfunktion (nicht als Hauptfunktion) beinhaltet. Firebase hat großzügige Limits für kostenlose Konten, aber ich habe mich gefragt, wie schnell Chaträume durch das Schreiben in die Datenbank (wie oben) anfallen können, wenn Ihre Benutzerbasis groß wird? Was denken Sie über einen Chat über Datenbank-Lese-/Schreibvorgänge im Vergleich zur Einrichtung einer kleinen Peer-to-Peer-Gruppe für Chats (nach der Authentifizierung von Benutzern und dem Finden aktiver Verbindungen über Firebase)?
Hallo, Tom
Die Firebase Realtime Database ist eine Cloud-gehostete NoSQL-Datenbank, mit der Sie Daten zwischen Ihren Benutzern in Echtzeit speichern und synchronisieren können, was bedeutet, dass es keine Geschwindigkeitsprobleme gibt, da alles in Echtzeit geschieht.
Wenn Sie Firebase verwenden, werde ich Ihnen empfehlen, eine Chat-App über Datenbank-Lese-/Schreibvorgänge zu machen. Das ist schneller und skalierbarer!
Beste Grüße,
Deven
Hallo Deven,
Tolles Tutorial – ich habe kürzlich versucht, eine Chat-App mit Firebase zu erstellen, habe mich aber angesichts der Skalierungsfaktoren im kostenlosen Plan dagegen entschieden. Meine Frage an Sie ist, wie skalierbar sehen Sie diese Chat-App?
Hallo, Meko
Mit dem kostenlosen Plan sehe ich nicht viel Skalierbarkeit mit Firebase, da Sie maximal 100 gleichzeitige Verbindungen mit nur 1 GB gespeicherten Daten haben können. Wenn Sie sich für einen kostenpflichtigen Plan entscheiden, ist die App auf jeder Ebene skalierbar. Viber ist das perfekte Beispiel!
Hey Deven, danke für das Tutorial. Gibt es einen Grund, warum Sie sich nicht für Funktionskomponenten entschieden haben?
HOCs (Higher-Order Components) teilen gemeinsame Funktionalität zwischen Komponenten, ohne Code zu wiederholen, was beim Schreiben von Code mit hohem Vergleichbarkeitsgrad hilft.
Hallo Deven, vielen Dank für diesen Beitrag, Mann! Sehr gründlich und einfach nachzuvollziehen!
Vielen Dank
Danke für das Tutorial. Ich möchte dies in meine Web-App für ein Team integrieren, um zu kommunizieren, aber ich habe diese Informationen erhalten, als ich versuchte, es zu implementieren
Fehler: Elementtyp ist ungültig: erwartete einen String (für integrierte Komponenten) oder eine Klasse/Funktion (für zusammengesetzte Komponenten), aber bekam: Objekt. Wahrscheinlich haben Sie vergessen, Ihre Komponente aus der Datei zu exportieren, in der sie definiert ist, oder Sie haben Standard- und benannte Importe verwechselt.
Sieht so aus, als hätten Sie vergessen, die Komponente zu exportieren, oder Sie exportieren ein React-Element, keine Komponente.
Vielen Dank für das nette Tutorial! Für jemanden, der mit React und Firebase experimentiert, war dies ein ausgezeichneter Start :)
Ein paar Anmerkungen dazu: Da ich den Code Abschnitt für Abschnitt beim Aufbau des Code-Basissystems verfolgt habe, kam es zu 2 Fehlern beim Erstellen des Projekts aufgrund von falsch übereinstimmendem oder fehlendem Code.
1. Im Abschnitt „Authentifizierung mit einem Google-Konto“ bindet der letzte Code-Schnipsel den GitHub-Authentifikator anstelle von Google.
2. Der Code für die Homepage fehlt im Tutorial vollständig. Ich musste die Git-Dateien eins zu eins durchgehen, um festzustellen, dass mir dies fehlte.
Nochmals vielen Dank für die nette Einführung :)
Tolles Tutorial, wirklich hilfreich, aber du hast mich beim Routing verloren, wo geht es hin? Es wird nicht in der Struktur gezeigt und du zeigst den Code, hast aber die Position im Beispiel weggelassen?
Danke für dieses Tutorial... Ich frage mich, ob es eine Möglichkeit gibt, benutzerdefinierte Benutzerfelder zum Firebase-Benutzerkonto hinzuzufügen?
Ich wäre sehr dankbar.. Danke
Es gibt einen Fehler im Tutorial, wenn Sie Google zur Anmeldeseite hinzufügen, verwenden Sie dies
Sollte es nicht heißen
Hallo Deven, vielen Dank für dieses Tutorial!
Gibt es einen Grund, warum Sie stattdessen keine Firestore verwendet haben?
Prost!
Luiz
Danke für das Tutorial! Es wäre toll, wenn Sie gezeigt hätten, wie das Routing in der App funktioniert.
Sie haben die ganze App am Anfang gezeigt, mein Fehler.
Das ist ein sehr schönes Tutorial. Aber da wir 2020 haben, wünschte ich, Sie hätten sich für einen Ansatz mit
Hooksentschieden. Hat jemand eine Hooks-basierte Version dieser App erstellt? Ich weiß, dass man die Authentifizierung in einen Context/Provider verschieben kann, bin mir aber nicht sicher, wie das alles funktionieren würde.Hey Deven,
Fantastischer Artikel. Wie würden Sie mehrere Chaträume machen? Würden Sie eine Echtzeitdatenbank für jeden Chatraum verwenden oder würden Sie vorschlagen, ein Array im Schema einer Echtzeitdatenbank zu erstellen und es als Beispiel `chatRooms` zu benennen und dann jeden Wert des Arrays zu einem eigenen Chatroom-Objekt mit einem Array für Chats zu machen?
Keine Listener hinzugefügt. Chatten beinhaltet mehr als eine Person. Sie chatten nur mit sich selbst. Warum nicht einen "child_added"-Listener oder etwas Ähnliches hinzufügen?
Wie unterscheiden Sie zwischen gesendeten und empfangenen Chats?
Hallo, tolles Tutorial! Ich habe bereits eine React Firebase App mit Google An- / Abmeldung usw. Wie würde ich diesen Chat in meine App integrieren?
danke
John