Project Templates
Social Network
Wie man ein soziales Netzwerk mit React aufbaut
121 min
einführung in diesem tutorial werden sie back4gram erstellen, eine voll funktionsfähige social network plattform, die instagram ähnelt back4gram ermöglicht es benutzern, konten zu erstellen, beiträge mit bildern zu teilen, durch likes und kommentare zu interagieren, nach inhalten zu suchen und über echtzeit nachrichten zu kommunizieren dieses projekt zeigt, wie man die leistungsstarken frontend funktionen von react mit den robusten backend diensten von back4app kombiniert, um eine moderne, funktionsreiche soziale anwendung zu erstellen react ist die perfekte wahl für das frontend eines sozialen netzwerks aufgrund seiner komponentenbasierten architektur, die wiederverwendbare ui elemente und effizientes rendering ermöglicht in der zwischenzeit bietet back4app einen verwalteten parse server backend, der die benutzerauthentifizierung, datenspeicherung, datei uploads und echtzeitfunktionen verwaltet, ohne dass sie eine komplexe serverinfrastruktur von grund auf neu erstellen müssen durch den abschluss dieses tutorials werden sie ein vollständiges soziales netzwerk mit benutzerauthentifizierung (registrierung, anmeldung, passwort zurücksetzen) profilverwaltung beitragserstellung mit bild uploads soziale interaktionen (likes, kommentare) echtzeit nachrichtenübermittlung mit tippanzeigen inhaltsuchfunktionalität benutzereinstellungen und präferenzen auf dem weg dorthin werden sie wertvolle fähigkeiten in folgenden bereichen erwerben react entwicklung mit hooks und kontext ui entwicklung mit chakra ui parse server integration über back4app echtzeit datenmanagement mit livequery benutzerauthentifizierungsabläufe datei upload verwaltung implementierung von responsive design egal, ob sie ihre eigene soziale plattform starten oder einfach verstehen möchten, wie moderne soziale netzwerke aufgebaut sind, dieses tutorial wird ihnen das wissen und die praktische erfahrung vermitteln, um ihre ziele zu erreichen zu jedem zeitpunkt können sie den vollständigen code auf github voraussetzungen um dieses tutorial abzuschließen, benötigen sie ein back4app konto registrieren sie sich für ein kostenloses konto bei back4app com https //www back4app com/ sie werden dies verwenden, um ihre backend dienste zu erstellen und zu verwalten node js und npm auf ihrem lokalen rechner installiert installieren sie node js (version 14 x oder höher) und npm von nodejs org https //nodejs org/ überprüfen sie ihre installation, indem sie node v und npm v in ihrem terminal grundlegendes verständnis von react vertrautheit mit react komponenten, hooks und jsx wenn sie ihr wissen über react auffrischen müssen, schauen sie sich die offizielle react dokumentation https //reactjs org/docs/getting started html code editor jeder moderne code editor wie visual studio code, sublime text oder atom git (optional) für die versionskontrolle und um mit dem repository schritt zu halten zusätzliche ressourcen back4app dokumentation https //www back4app com/docs/get started/welcome parse javascript anleitung https //docs parseplatform org/js/guide/ chakra ui dokumentation https //chakra ui com/docs/getting started react router dokumentation https //reactrouter com/en/main schritt 1 — einrichten ihres back4app backends in diesem schritt erstellen sie ein neues back4app projekt und konfigurieren das datenbankschema, das für ihre social network anwendung erforderlich ist back4app bietet einen verwalteten parse server, der die benutzerauthentifizierung, die datenspeicherung und echtzeitfunktionen übernimmt erstellen eines neuen back4app projekts melden sie sich bei ihrem back4app konto an und navigieren sie zum dashboard klicken sie auf die schaltfläche "eine neue app erstellen" geben sie "back4gram" als ihren app namen ein, wählen sie die nächstgelegene serverregion aus und klicken sie auf "erstellen" sobald ihre app erstellt ist, werden sie zum app dashboard weitergeleitet das verständnis des datenbankschemas bevor wir klassen in ihrer datenbank erstellen, lassen sie uns das datenmodell verstehen, das für unser soziales netzwerk benötigt wird basierend auf den anforderungen unserer anwendung benötigen wir die folgenden klassen benutzer (existiert bereits standardmäßig in parse) diese klasse verwaltet die benutzerauthentifizierung und profilinformationen wir werden es mit zusätzlichen feldern wie biografie und avatar erweitern beitrag speichert benutzerbeiträge einschließlich textinhalten und bildern felder inhalt (string), autor (zeiger auf benutzer), bild (datei), likes (zahl), kommentare (array), erstellt am (datum) kommentar speichert kommentare zu beiträgen felder inhalt (string), autor (zeiger auf benutzer), beitrag (zeiger auf beitrag), erstellt am (datum) gespräch stellt ein chat gespräch zwischen benutzern dar felder teilnehmer (array von zeigern auf benutzer), letztenachricht (string), aktualisiertam (datum) nachricht einzelne nachrichten innerhalb eines gesprächs felder text (string), sender (zeiger auf benutzer), conversation (zeiger auf unterhaltung), createdat (datum) tippstatus (für echtzeit tippindikatoren) verfolgt, wenn benutzer in einem gespräch tippen felder benutzer (zeiger auf benutzer), unterhaltung (zeiger auf unterhaltung), isttippen (boolean) datenbankklassen erstellen lass uns jetzt diese klassen in deiner back4app datenbank erstellen navigieren sie zum abschnitt "datenbank" in ihrem back4app dashboard die benutzerklasse erweitern klicken sie auf die bereits vorhandene "benutzer" klasse fügen sie die folgenden spalten hinzu bio (typ zeichenfolge) avatar (typ datei) follower (typ zahl, standard 0) folgend (typ zahl, standard 0) die post klasse erstellen klicken sie auf "eine klasse erstellen" geben sie "post" als klassennamen ein und wählen sie "eine leere klasse erstellen" fügen sie die folgenden spalten hinzu inhalt (typ zeichenfolge) autor (typ zeiger auf benutzer) bild (typ datei) gefällt mir (typ zahl, standard 0) kommentare (typ array) erstelltam (typ datum, automatisch hinzugefügt) erstellen der kommentar klasse klicken sie auf "eine klasse erstellen" geben sie "kommentar" als klassennamen ein und wählen sie "eine leere klasse erstellen" fügen sie die folgenden spalten hinzu inhalt (typ zeichenfolge) autor (typ zeiger auf benutzer) beitrag (typ zeiger auf beitrag) erstelltam (typ datum, automatisch hinzugefügt) die conversation klasse erstellen klicken sie auf "eine klasse erstellen" geben sie "conversation" als klassennamen ein und wählen sie "eine leere klasse erstellen" fügen sie die folgenden spalten hinzu teilnehmer (typ array) letztenachricht (typ string) aktualisiertam (typ datum, automatisch hinzugefügt) erstellen der message klasse klicken sie auf "eine klasse erstellen" geben sie "nachricht" als klassennamen ein und wählen sie "eine leere klasse erstellen" fügen sie die folgenden spalten hinzu text (typ zeichenfolge) absender (typ zeiger auf user) gespräch (typ zeiger auf gespräch) erstelltam (typ datum, automatisch hinzugefügt) erstellen der typingstatus klasse klicken sie auf "eine klasse erstellen" geben sie "typingstatus" als klassennamen ein und wählen sie "eine leere klasse erstellen" fügen sie die folgenden spalten hinzu benutzer (typ zeiger auf benutzer) gespräch (typ zeiger auf gespräch) tippt (typ boolean) einrichten von klassenberechtigungen (optional) um die datensicherheit zu gewährleisten, müssen wir geeignete zugriffskontrolllisten (acls) für jede klasse konfigurieren navigieren sie zum abschnitt "sicherheit & schlüssel" in ihrem back4app dashboard unter "klassenstufen sicherheit" konfigurieren sie die folgenden berechtigungen benutzerklasse öffentlicher lesezugriff aktiviert (damit benutzer die profile anderer benutzer sehen können) öffentlicher schreibzugriff deaktiviert (benutzer können nur ihre eigenen profile bearbeiten) beitragsklasse öffentlicher lesezugriff aktiviert (jeder kann beiträge sehen) öffentlicher schreibzugriff aktiviert (authentifizierte benutzer können beiträge erstellen) fügen sie eine clp für aktualisierung/löschung hinzu, um nur den autor einzuschränken kommentar klasse öffentlicher lesezugriff aktiviert (jeder kann kommentare sehen) öffentlicher schreibzugriff aktiviert (authentifizierte benutzer können kommentare erstellen) fügen sie eine clp für aktualisierung/löschung hinzu, um nur den autor zu beschränken gesprächsklasse öffentlicher lesezugriff deaktiviert (gespräche sind privat) öffentlicher schreibzugriff aktiviert (authentifizierte benutzer können gespräche erstellen) fügen sie ein clp hinzu, um den lese /schreibzugriff für teilnehmer an gesprächen einzuschränken nachricht klasse öffentlicher lesezugriff deaktiviert (nachrichten sind privat) öffentlicher schreibzugriff aktiviert (authentifizierte benutzer können nachrichten senden) fügen sie ein clp hinzu, um den lese /schreibzugriff für teilnehmer an gesprächen einzuschränken typingstatus klasse öffentlicher lesezugriff deaktiviert (tippstatus ist privat) öffentlicher schreibzugriff aktiviert (authentifizierte benutzer können den schreibstatus aktualisieren) fügen sie ein clp hinzu, um den lese /schreibzugriff für teilnehmer an gesprächen einzuschränken einrichten von livequery für echtzeitfunktionen um echtzeitfunktionen wie messaging und tippindikatoren zu aktivieren, müssen wir livequery konfigurieren navigieren sie zum abschnitt "servereinstellungen" in ihrem back4app dashboard unter "parse server" finden sie den abschnitt "livequery" und aktivieren sie ihn fügen sie die folgenden klassen hinzu, die von livequery überwacht werden sollen nachricht tippstatus beitrag (für echtzeit updates zu likes und kommentaren) ändern sie ihre änderungen erhalten ihrer anwendungs schlüssel sie benötigen ihre back4app anwendungsschlüssel, um ihr react frontend mit dem backend zu verbinden navigieren sie zu "app einstellungen" > "sicherheit & schlüssel" notieren sie sich die folgenden schlüssel anwendungs id javascript schlüssel server url livequery server url (subdomain konfiguration, für echtzeitfunktionen) sie verwenden diese schlüssel in ihrer react anwendung, um parse zu initialisieren schritt 2 — erstellen eines react frontend projekts in diesem schritt richten sie ein neues react projekt ein und konfigurieren es, um mit ihrem back4app backend zu arbeiten sie installieren die erforderlichen abhängigkeiten, erstellen die projektstruktur und verbinden sich mit ihrem parse server einrichten eines neuen react projekts lass uns damit beginnen, eine neue react anwendung mit create react app zu erstellen, die eine moderne build konfiguration ohne einrichtung bietet öffne dein terminal und navigiere zu dem verzeichnis, in dem du dein projekt erstellen möchtest führe den folgenden befehl aus, um eine neue react anwendung zu erstellen npx create react app back4gram sobald das projekt erstellt ist, navigiere zum projektverzeichnis cd back4gram starte den entwicklungsserver, um sicherzustellen, dass alles funktioniert npm start dies öffnet deine neue react anwendung in deinem browser unter http //localhost 3000 http //localhost 3000 notwendige abhängigkeiten installieren jetzt lass uns die pakete installieren, die wir für unsere social network anwendung benötigen stoppen sie den entwicklungsserver (drücken sie ctrl+c in ihrem terminal) installieren sie das parse sdk zur verbindung mit back4app npm install parse installieren sie react router für die navigation npm install react router dom installieren sie chakra ui für unsere benutzeroberflächenkomponenten npm install @chakra ui/react @emotion/react @emotion/styled framer motion installieren sie zusätzliche ui dienstprogramme und icon bibliotheken npm install react icons erklärung der projektstruktur lassen sie uns unser projekt mit einer klaren struktur organisieren erstellen sie die folgenden verzeichnisse im src ordner mkdir p src/components/ui src/pages src/contexts src/utils hier ist, wofür jedes verzeichnis gedacht ist components wiederverwendbare ui komponenten ui grundlegende ui komponenten wie schaltflächen, formulare, modale andere komponentenordner für spezifische funktionen (z b beiträge, kommentare) pages vollseitige komponenten, die den routen entsprechen contexts react kontextanbieter für das zustandsmanagement utils hilfsfunktionen und werkzeuge umgebungsvariablen erstellen um ihre back4app anmeldeinformationen sicher zu speichern, erstellen sie eine env datei im stammverzeichnis ihres projekts erstellen sie eine neue datei mit dem namen env local im stammverzeichnis des projekts touch env local öffnen sie die datei und fügen sie ihre back4app anmeldeinformationen hinzu react app parse app id=your application id react app parse js key=your javascript key react app parse server url=https //parseapi back4app com react app parse live query url=wss\ //your app id back4app io ersetzen sie die platzhalterwerte durch ihre tatsächlichen back4app anmeldeinformationen aus schritt 1 stellen sie sicher, dass sie env local zu ihrer gitignore datei hinzufügen, um zu verhindern, dass sensible informationen eingegeben werden konfigurieren des parse sdk mit back4app anmeldeinformationen jetzt richten wir das parse sdk ein, um eine verbindung zu ihrem back4app backend herzustellen erstellen sie eine neue datei src/utils/parseconfig js // src/utils/parseconfig js import parse from 'parse/dist/parse min js'; // initialize parse parse initialize( process env react app parse app id, process env react app parse js key ); parse serverurl = process env react app parse server url; // initialize live queries if (process env react app parse live query url) { parse livequeryserverurl = process env react app parse live query url; } export default parse; aktualisieren sie ihre src/index js datei, um die parse konfiguration zu importieren import react from 'react'; import reactdom from 'react dom/client'; import ' /index css'; import app from ' /app'; import reportwebvitals from ' /reportwebvitals'; import ' /utils/parseconfig'; // import parse konfiguration const root = reactdom createroot(document getelementbyid('root')); root render( \<react strictmode> \<app /> \</react strictmode> ); reportwebvitals(); einrichten der app komponente mit routing lass uns die haupt app komponente aktualisieren, um routing und den chakra ui anbieter einzuschließen aktualisieren src/app js import react from 'react'; import { browserrouter as router, routes, route } from 'react router dom'; import { chakraprovider, extendtheme } from '@chakra ui/react'; // seiten importieren (wir werden diese als nächstes erstellen) import landingpage from ' /pages/landingpage'; import loginpage from ' /pages/loginpage'; import signuppage from ' /pages/signuppage'; import resetpasswordpage from ' /pages/resetpasswordpage'; import feedpage from ' /pages/feedpage'; import profilepage from ' /pages/profilepage'; import postdetailspage from ' /pages/postdetailspage'; import messagespage from ' /pages/messagespage'; import searchpage from ' /pages/searchpage'; import settingspage from ' /pages/settingspage'; // ein benutzerdefiniertes thema erstellen const theme = extendtheme({ config { initialcolormode 'dark', usesystemcolormode false, }, colors { brand { 50 '#e5f4ff', 100 '#b8dcff', 200 '#8ac5ff', 300 '#5cadff', 400 '#2e96ff', 500 '#147dff', 600 '#0061cc', 700 '#004799', 800 '#002d66', 900 '#001433', }, }, }); function app() { return ( \<chakraprovider theme={theme}> \<router> \<routes> \<route path="/" element={\<landingpage />} /> \<route path="/login" element={\<loginpage />} /> \<route path="/signup" element={\<signuppage />} /> \<route path="/reset password" element={\<resetpasswordpage />} /> \<route path="/feed" element={\<feedpage />} /> \<route path="/profile" element={\<profilepage />} /> \<route path="/post/\ id" element={\<postdetailspage />} /> \<route path="/messages" element={\<messagespage />} /> \<route path="/search" element={\<searchpage />} /> \<route path="/settings" element={\<settingspage />} /> \</routes> \</router> \</chakraprovider> ); } export default app; erstellen einer geschützten routenkomponente um routen zu sichern, die eine authentifizierung erfordern, lassen sie uns eine protectedroute komponente erstellen zuerst erstellen sie einen authcontext, um den authentifizierungsstatus des benutzers zu verwalten // src/contexts/authcontext js import react, { createcontext, usestate, usecontext, useeffect } from 'react'; import parse from 'parse/dist/parse min js'; const authcontext = createcontext(); export function useauth() { return usecontext(authcontext); } export function authprovider({ children }) { const \[currentuser, setcurrentuser] = usestate(null); const \[isloading, setisloading] = usestate(true); useeffect(() => { // check if user is already logged in const checkuser = async () => { try { const user = await parse user current(); setcurrentuser(user); } catch (error) { console error('error checking current user ', error); } finally { setisloading(false); } }; checkuser(); }, \[]); // login function const login = async (username, password) => { try { const user = await parse user login(username, password); setcurrentuser(user); return user; } catch (error) { throw error; } }; // signup function const signup = async (username, email, password) => { try { const user = new parse user(); user set('username', username); user set('email', email); user set('password', password); const result = await user signup(); setcurrentuser(result); return result; } catch (error) { throw error; } }; // logout function const logout = async () => { try { await parse user logout(); setcurrentuser(null); } catch (error) { throw error; } }; // reset password function const resetpassword = async (email) => { try { await parse user requestpasswordreset(email); } catch (error) { throw error; } }; const value = { currentuser, isloading, login, signup, logout, resetpassword, }; return \<authcontext provider value={value}>{children}\</authcontext provider>; } erstellen sie jetzt die protectedroute komponente // src/components/protectedroute js import react from 'react'; import { navigate } from 'react router dom'; import { useauth } from ' /contexts/authcontext'; import { flex, spinner } from '@chakra ui/react'; function protectedroute({ children }) { const { currentuser, isloading } = useauth(); if (isloading) { return ( \<flex justify="center" align="center" height="100vh"> \<spinner size="xl" /> \</flex> ); } if (!currentuser) { return \<navigate to="/login" />; } return children; } export default protectedroute; aktualisieren sie die app komponente, um den authprovider und die protectedroute zu verwenden // src/app js (updated) import react from 'react'; import { browserrouter as router, routes, route } from 'react router dom'; import { chakraprovider, extendtheme } from '@chakra ui/react'; import { authprovider } from ' /contexts/authcontext'; import protectedroute from ' /components/protectedroute'; // import pages import landingpage from ' /pages/landingpage'; import loginpage from ' /pages/loginpage'; import signuppage from ' /pages/signuppage'; import resetpasswordpage from ' /pages/resetpasswordpage'; import feedpage from ' /pages/feedpage'; import profilepage from ' /pages/profilepage'; import postdetailspage from ' /pages/postdetailspage'; import messagespage from ' /pages/messagespage'; import searchpage from ' /pages/searchpage'; import settingspage from ' /pages/settingspage'; // theme configuration (same as before) const theme = extendtheme({ // theme configuration }); function app() { return ( \<chakraprovider theme={theme}> \<authprovider> \<router> \<routes> \<route path="/" element={\<landingpage />} /> \<route path="/login" element={\<loginpage />} /> \<route path="/signup" element={\<signuppage />} /> \<route path="/reset password" element={\<resetpasswordpage />} /> \<route path="/feed" element={ \<protectedroute> \<feedpage /> \</protectedroute> } /> \<route path="/profile" element={ \<protectedroute> \<profilepage /> \</protectedroute> } /> \<route path="/post/\ id" element={ \<protectedroute> \<postdetailspage /> \</protectedroute> } /> \<route path="/messages" element={ \<protectedroute> \<messagespage /> \</protectedroute> } /> \<route path="/search" element={ \<protectedroute> \<searchpage /> \</protectedroute> } /> \<route path="/settings" element={ \<protectedroute> \<settingspage /> \</protectedroute> } /> \</routes> \</router> \</authprovider> \</chakraprovider> ); } export default app; erstellen einer einfachen landing page lass uns eine einfache landing page erstellen, um unser setup zu testen // src/pages/landingpage js import react from 'react'; import { box, heading, text, button, vstack, flex } from '@chakra ui/react'; import { link as routerlink } from 'react router dom'; function landingpage() { return ( \<box bg="gray 900" minh="100vh" color="white"> \<flex direction="column" align="center" justify="center" textalign="center" py={20} \> \<heading size="2xl" mb={4}> back4gram \</heading> \<text fontsize="lg" maxw="600px" mb={8}> join a vibrant community where your voice matters share stories, ideas, and moments with friends and the world \</text> \<vstack spacing={4} maxw="md" mx="auto"> \<button as={routerlink} to="/signup" colorscheme="brand" size="lg" w="full" \> create account \</button> \<button as={routerlink} to="/login" variant="outline" size="lg" w="full" \> log in \</button> \</vstack> \</flex> \</box> ); } export default landingpage; testen sie ihre einrichtung jetzt, da sie die grundlegende struktur ihrer react anwendung eingerichtet und mit back4app verbunden haben, lassen sie uns testen starten sie den entwicklungsserver npm start öffnen sie ihren browser und navigieren sie zu http //localhost 3000 http //localhost 3000 sie sollten die startseite mit schaltflächen zum anmelden oder registrieren sehen überprüfen sie die konsole ihres browsers, um sicherzustellen, dass keine fehler im zusammenhang mit der parse initialisierung vorliegen schritt 3 — implementierung von authentifizierungsfunktionen in diesem schritt werden wir die benutzer authentifizierungsfunktionen für unsere social network anwendung mit dem parse server von back4app implementieren wir werden untersuchen, wie das parse authentifizierungssystem funktioniert und die funktionen für anmeldung, registrierung und passwortzurücksetzung implementieren verstehen des parse benutzerauthentifizierungssystems der parse server von back4app bietet ein umfassendes benutzermanagementsystem über die parse user klasse lassen sie uns verstehen, wie die parse authentifizierung in unserer anwendung funktioniert die parse user klasse die parse user klasse ist eine spezielle unterklasse von parse object , die speziell für das benutzermanagement entwickelt wurde in unserer back4gram anwendung verwenden wir sie, um benutzerdaten (benutzername, e mail, passwort) speichern authentifizierungsstatus verwalten sitzungstoken automatisch verwalten wenn wir uns unsere implementierung ansehen, können wir sehen, wie wir mit der parse user klasse interagieren // from signuppage js const user = new parse user(); user set('username', username); user set('email', email); user set('password', password); await user signup(); dieser code erstellt ein neues parse user objekt, setzt die erforderlichen felder und ruft die methode signup() auf, um den benutzer in back4app zu registrieren authentifizierungsfluss in parse lassen sie uns untersuchen, wie die authentifizierung in unserer anwendung funktioniert registrierungsablauf in unserer signuppage js sammeln wir benutzernamen, e mail und passwort wir validieren die eingabedaten (überprüfung auf leere felder, gültiges e mail format, passwortlänge) wir erstellen ein neues parse user objekt und setzen die anmeldeinformationen wir rufen signup() auf, das die daten an back4app sendet parse hasht das passwort, bevor es gespeichert wird bei erfolg wird der benutzer automatisch mit einem sitzungstoken angemeldet anmeldefluss in unserer loginpage js sammeln wir benutzernamen und passwort wir rufen parse user login() mit diesen anmeldeinformationen auf parse überprüft die anmeldeinformationen gegen die gespeicherten daten wenn gültig, generiert parse ein sitzungstoken das sitzungstoken wird automatisch im browser speicher gespeichert sitzungsverwaltung parse fügt automatisch das sitzungstoken in alle api anfragen ein wir verwenden parse user current(), um den aktuell angemeldeten benutzer abzurufen sitzungen bleiben über seitenaktualisierungen hinweg bestehen benutzeregistrierung implementieren lassen sie uns unsere signuppage komponente untersuchen, um zu verstehen, wie die benutzeregistrierung implementiert ist formularvalidierung bevor wir daten an back4app senden, validieren wir die benutzereingaben // from signuppage js const validateform = () => { const newerrors = {}; if (!username trim()) { newerrors username = 'username is required'; } if (!email trim()) { newerrors email = 'email is required'; } else if (!/\s+@\s+\\ \s+/ test(email)) { newerrors email = 'email is invalid'; } if (!password) { newerrors password = 'password is required'; } else if (password length < 6) { newerrors password = 'password must be at least 6 characters'; } if (password !== confirmpassword) { newerrors confirmpassword = 'passwords do not match'; } seterrors(newerrors); return object keys(newerrors) length === 0; }; diese validierung stellt sicher, dass benutzername ist nicht leer e mail ist gültig passwort hat mindestens 6 zeichen passwort und bestätigung stimmen überein behandlung von registrierungsfehlern unser anmeldehandler umfasst die fehlerbehandlung für parse spezifische fehler // from signuppage js try { // create a new user const user = new parse user(); user set('username', username); user set('email', email); user set('password', password); await user signup(); toaster create({ title 'success', description 'account created successfully!', type 'success', }); navigate('/feed'); } catch (error) { toaster create({ title 'signup failed', description error message, type 'error', }); // handle specific parse errors if (error code === 202) { seterrors({ errors, username 'username already taken'}); } else if (error code === 203) { seterrors({ errors, email 'email already in use'}); } } back4app gibt spezifische fehlercodes zurück, die wir verwenden können, um hilfreiches feedback an den benutzer zu geben code 202 benutzername bereits vergeben code 203 e mail bereits in verwendung der vollständige code für die benutzerregistrierung/anmeldung ist hier zu finden implementierung der benutzeranmeldung unsere loginpage komponente behandelt die benutzerauthentifizierung mit parse user login() anmeldeformular das anmeldeformular sammelt benutzername und passwort // from loginpage js \<form onsubmit={handlelogin}> \<vstack spacing={4}> \<field label="username"> \<input type="text" value={username} onchange={(e) => setusername(e target value)} placeholder="your username" required /> \</field> \<field label="password" errortext={error} \> \<input type="password" value={password} onchange={(e) => setpassword(e target value)} placeholder="your password" required /> \</field> \<link as={routerlink} to="/reset password" alignself="flex end" fontsize="sm"> forgot password? \</link> \<button colorscheme="blue" width="full" type="submit" loading={isloading} \> log in \</button> \</vstack> \</form> sitzungsüberprüfung wie bereits erwähnt, überprüfen wir beim laden der anmeldeseite, ob eine vorhandene sitzung besteht // from loginpage js useeffect(() => { const checkcurrentuser = async () => { try { const user = await parse user current(); if (user) { setcurrentuser(user); navigate('/feed'); } } catch (error) { console error('error checking current user ', error); } }; checkcurrentuser(); }, \[navigate]); dies ist ein wichtiges merkmal von parse es verwaltet automatisch das sitzungstoken im browser speicher, sodass wir leicht überprüfen können, ob ein benutzer bereits angemeldet ist implementierung der passwortzurücksetzung back4app bietet einen integrierten ablauf zur passwortzurücksetzung in unserer anwendung verlinken wir von dem anmeldeformular zu einer seite zur passwortzurücksetzung // from loginpage js \<link as={routerlink} to="/reset password" alignself="flex end" fontsize="sm"> forgot password? \</link> der prozess zur passwortzurücksetzung in back4app funktioniert wie folgt der benutzer fordert eine passwortzurücksetzung mit seiner e mail an parse sendet einen speziellen rücksetzlink an die e mail des benutzers der benutzer klickt auf den link und setzt ein neues passwort parse aktualisiert den passwort hash in der datenbank um dies in unserer anwendung zu implementieren, würden wir verwenden // example password reset implementation try { await parse user requestpasswordreset(email); // show success message } catch (error) { // handle error } routen für authentifizierte benutzer sichern um bestimmte routen in unserer anwendung zu schützen, verwenden wir eine protectedroute komponente, die überprüft, ob ein benutzer authentifiziert ist // from protectedroute js function protectedroute({ children }) { const { currentuser, isloading } = useauth(); if (isloading) { return ( \<flex justify="center" align="center" height="100vh"> \<spinner size="xl" /> \</flex> ); } if (!currentuser) { return \<navigate to="/login" />; } return children; } diese komponente verwendet unseren authcontext, um zu überprüfen, ob ein benutzer angemeldet ist zeigt einen ladeindikator während der überprüfung an leitet zur anmeldeseite weiter, wenn kein benutzer gefunden wird rendert den geschützten inhalt, wenn ein benutzer authentifiziert ist wir verwenden diese komponente in unserem routing setup // from app js \<route path="/feed" element={ \<protectedroute> \<feedpage /> \</protectedroute> } /> back4app authentifizierungskonfiguration back4app bietet mehrere konfigurationsoptionen für die authentifizierung im dashboard an e mail verifizierung sie können eine e mail verifizierung verlangen, bevor benutzer sich anmelden können konfigurieren sie dies in "servereinstellungen" > "parse server" > "benutzerauthentifizierung" passwort richtlinie legen sie die mindestlänge und komplexitätsanforderungen für passwörter fest konfigurieren sie dies in "servereinstellungen" > "parse server" > "benutzerauthentifizierung" sitzungsdauer steuern sie, wie lange benutzersitzungen gültig bleiben konfigurieren sie dies in "servereinstellungen" > "parse server" > "sitzungskonfiguration" e mail vorlagen passen sie die e mails zur verifizierung und passwortzurücksetzung an konfigurieren sie dies in "app einstellungen" > "e mail vorlagen" testen sie ihre authentifizierungsimplementierung um sicherzustellen, dass ihr authentifizierungssystem korrekt funktioniert testbenutzerregistrierung versuchen sie, sich mit gültigen anmeldeinformationen zu registrieren versuchen sie, sich mit einem vorhandenen benutzernamen zu registrieren (sollte einen fehler anzeigen) überprüfen sie, ob der benutzer in ihrem back4app dashboard unter der klasse " user" erscheint testbenutzeranmeldung versuchen sie, sich mit korrekten anmeldeinformationen anzumelden (sollte zur feed seite umleiten) versuchen sie, sich mit falschen anmeldeinformationen anzumelden (sollte einen fehler anzeigen) test der sitzungsbeständigkeit melden sie sich an und aktualisieren sie die seite (sollte angemeldet bleiben) schließen und öffnen sie den browser erneut (sollte angemeldet bleiben, wenn die sitzung gültig ist) test geschützter routen versuchen sie, auf /feed zuzugreifen, wenn sie abgemeldet sind (sollte zur anmeldeseite umleiten) versuchen sie, auf /feed zuzugreifen, wenn sie angemeldet sind (sollte die feed seite anzeigen) der code für die login komponente ist hier zu finden schritt 4 — entwicklung der feed funktionalität in diesem schritt implementierst du die zentrale funktion des sozialen netzwerks den feed hier werden benutzer beiträge erstellen, inhalte von anderen ansehen und durch likes und kommentare interagieren wir werden den parse server von back4app verwenden, um beiträge zu speichern und abzurufen, datei uploads für bilder zu handhaben und echtzeit updates zu implementieren verstehen der struktur der feed seite die feed seite in unserer anwendung hat drei hauptkomponenten eine seitenleiste zur navigation der hauptbereich für beiträge mit erstellung und auflistung von beiträgen ein trendbereich (auf größeren bildschirmen) lass uns untersuchen, wie dies in unserer feedpage js implementiert ist // from feedpage js main structure function feedpage() { // state and hooks return ( \<flex minh="100vh" bg="gray 800" color="white"> {/ left sidebar (navigation) /} \<box w={\['0px', '200px']} bg="gray 900" p={4} display={\['none', 'block']}> {/ navigation links /} \</box> {/ main content (feed) /} \<box flex="1" p={4} overflowy="auto"> {/ post creation form /} {/ posts list /} \</box> {/ right sidebar (trending) /} \<box w={\['0px', '250px']} bg="gray 700" p={4} display={\['none', 'block']}> {/ trending content /} \</box> \</flex> ); } dieses responsive layout passt sich an verschiedene bildschirmgrößen an und blendet die seitenleisten auf mobilen geräten aus erstellung der post klasse in back4app bevor wir das frontend implementieren, stellen wir sicher, dass unsere back4app datenbank ordnungsgemäß für beiträge eingerichtet ist die post klasse sollte die folgenden felder haben inhalt (string) der textinhalt des beitrags bild (datei) optionaler bildanhang autor (verweis auf benutzer) der benutzer, der den beitrag erstellt hat likes (zahl) anzahl der likes auf dem beitrag gemocht von (array) array von benutzer ids, die den beitrag gemocht haben erstellt am (datum) automatisch von parse hinzugefügt setzen sie die entsprechenden berechtigungen für die post klasse öffentlicher lesezugriff jeder sollte in der lage sein, beiträge zu lesen öffentlicher schreibzugriff authentifizierte benutzer sollten in der lage sein, beiträge zu erstellen update /löschberechtigungen nur der autor sollte in der lage sein, seine beiträge zu ändern implementierung der beitragserstellung lass uns untersuchen, wie die erstellung von beiträgen in unserer feedpage komponente implementiert ist // from feedpage js post creation state const \[postcontent, setpostcontent] = usestate(''); const \[postimage, setpostimage] = usestate(null); const \[imagepreview, setimagepreview] = usestate(''); const \[issubmitting, setissubmitting] = usestate(false); // image selection handler const handleimageselect = (e) => { if (e target files && e target files\[0]) { const file = e target files\[0]; setpostimage(file); // create preview url const previewurl = url createobjecturl(file); setimagepreview(previewurl); } }; // post submission handler const handlesubmitpost = async () => { if (!postcontent trim() && !postimage) { toaster create({ title 'error', description 'please add some text or an image to your post', type 'error', }); return; } setissubmitting(true); try { // create a new post object const post = parse object extend('post'); const newpost = new post(); // set post content newpost set('content', postcontent); newpost set('author', parse user current()); newpost set('likes', 0); newpost set('likedby', \[]); // if there's an image, upload it if (postimage) { const parsefile = new parse file(postimage name, postimage); await parsefile save(); newpost set('image', parsefile); } // save the post await newpost save(); // reset form setpostcontent(''); setpostimage(null); setimagepreview(''); // refresh posts fetchposts(); toaster create({ title 'success', description 'your post has been published!', type 'success', }); } catch (error) { toaster create({ title 'error', description error message, type 'error', }); } finally { setissubmitting(false); } }; wichtige punkte zur erstellung von beiträgen dateiverwaltung in parse parse file wird verwendet, um bilder in den speicher von back4app hochzuladen die datei wird zuerst gespeichert und dann dem beitragsobjekt angehängt back4app verwaltet automatisch die dateispeicherung und generiert urls erstellen von parse objekten wir erweitern die 'post' klasse mit parse object extend('post') wir erstellen eine neue instanz mit new post() wir setzen eigenschaften mit der set() methode wir speichern das objekt bei back4app mit save() benutzerzuordnung wir verknüpfen den beitrag mit dem aktuellen benutzer über parse user current() dies erstellt eine zeigerbeziehung in der datenbank das ui formular zur erstellung von beiträgen sieht so aus {/ post creation form /} \<box mb={6} bg="gray 700" p={4} borderradius="md"> \<vstack align="stretch" spacing={4}> \<textarea placeholder="what's on your mind?" value={postcontent} onchange={(e) => setpostcontent(e target value)} minh="100px" /> {imagepreview && ( \<box position="relative"> \<image src={imagepreview} maxh="200px" borderradius="md" /> \<iconbutton icon={\<closeicon />} size="sm" position="absolute" top="2" right="2" onclick={() => { setpostimage(null); setimagepreview(''); }} /> \</box> )} \<hstack> \<button lefticon={\<attachmenticon />} onclick={() => document getelementbyid('image upload') click()} \> add image \</button> \<input id="image upload" type="file" accept="image/ " onchange={handleimageselect} display="none" /> \<button colorscheme="blue" ml="auto" isloading={issubmitting} onclick={handlesubmitpost} disabled={(!postcontent trim() && !postimage) || issubmitting} \> post \</button> \</hstack> \</vstack> \</box> beiträge abrufen und anzeigen schauen wir uns jetzt an, wie wir beiträge von back4app abrufen und anzeigen // from feedpage js fetching posts const \[posts, setposts] = usestate(\[]); const \[isloading, setisloading] = usestate(true); const \[page, setpage] = usestate(0); const \[hasmore, sethasmore] = usestate(true); const postsperpage = 10; const fetchposts = async (loadmore = false) => { try { const currentpage = loadmore ? page + 1 0; // create a query for the post class const post = parse object extend('post'); const query = new parse query(post); // include the author object (pointer) query include('author'); // sort by creation date, newest first query descending('createdat'); // pagination query limit(postsperpage); query skip(currentpage postsperpage); // execute the query const results = await query find(); // process the results const fetchedposts = results map(post => ({ id post id, content post get('content'), image post get('image') ? post get('image') url() null, likes post get('likes') || 0, likedby post get('likedby') || \[], createdat post get('createdat'), author { id post get('author') id, username post get('author') get('username'), avatar post get('author') get('avatar') ? post get('author') get('avatar') url() null } })); // update state if (loadmore) { setposts(prevposts => \[ prevposts, fetchedposts]); setpage(currentpage); } else { setposts(fetchedposts); setpage(0); } // check if there are more posts to load sethasmore(results length === postsperpage); } catch (error) { console error('error fetching posts ', error); toaster create({ title 'error', description 'failed to load posts please try again ', type 'error', }); } finally { setisloading(false); } }; // load posts when component mounts useeffect(() => { fetchposts(); }, \[]); wichtige punkte zum abrufen von beiträgen abfrage parser wir erstellen eine abfrage mit new parse query(post) wir schließen verwandte objekte mit query include('author') wir sortieren mit query descending('createdat') wir paginieren mit query limit() und query skip() wir führen die abfrage mit query find() verarbeitung der ergebnisse parse objekte haben eine get() methode, um auf eigenschaften zuzugreifen für dateifelder verwenden wir file url() um die url zu erhalten wir transformieren parse objekte in einfache javascript objekte für den react zustand paginierung wir implementieren die funktionalität "mehr laden" mit seitenverfolgung wir überprüfen, ob es weitere beiträge zum laden gibt, bevor wir zusätzliche anfragen stellen die beiträge werden in einer liste angezeigt {/ posts list /} {isloading ? ( \<center py={10}> \<spinner size="xl" /> \</center> ) posts length > 0 ? ( \<vstack spacing={4} align="stretch"> {posts map(post => ( \<box key={post id} p={4} bg="gray 700" borderradius="md"> {/ post header with author info /} \<hstack mb={2}> \<avatar root size="sm"> \<avatar fallback name={post author username} /> \<avatar image src={post author avatar} /> \</avatar root> \<text fontweight="bold">{post author username}\</text> \<text fontsize="sm" color="gray 400">• {formatdate(post createdat)}\</text> \</hstack> {/ post content /} \<text mb={4}>{post content}\</text> {/ post image if any /} {post image && ( \<image src={post image} maxh="400px" borderradius="md" mb={4} /> )} {/ post actions /} \<hstack> \<button variant="ghost" lefticon={\<likeicon />} onclick={() => handlelikepost(post id, post likedby)} color={post likedby includes(currentuser id) ? "blue 400" "white"} \> {post likes} likes \</button> \<button variant="ghost" lefticon={\<commenticon />} as={routerlink} to={`/post/${post id}`} \> comments \</button> \</hstack> \</box> ))} {/ load more button /} {hasmore && ( \<button onclick={() => fetchposts(true)} isloading={isloadingmore}> load more \</button> )} \</vstack> ) ( \<center py={10}> \<text>no posts yet be the first to post!\</text> \</center> )} implementierung der like funktionalität lass uns untersuchen, wie die like funktionalität implementiert ist // from feedpage js like functionality const handlelikepost = async (postid, likedby) => { try { const currentuserid = parse user current() id; const isliked = likedby includes(currentuserid); // get the post object const post = parse object extend('post'); const query = new parse query(post); const post = await query get(postid); // update likes count and likedby array if (isliked) { // unlike remove user from likedby and decrement likes post set('likedby', likedby filter(id => id !== currentuserid)); post set('likes', (post get('likes') || 1) 1); } else { // like add user to likedby and increment likes post set('likedby', \[ likedby, currentuserid]); post set('likes', (post get('likes') || 0) + 1); } // save the updated post await post save(); // update local state setposts(prevposts => prevposts map(p => p id === postid ? { p, likes isliked ? p likes 1 p likes + 1, likedby isliked ? p likedby filter(id => id !== currentuserid) \[ p likedby, currentuserid] } p ) ); } catch (error) { console error('error liking post ', error); toaster create({ title 'error', description 'failed to like post please try again ', type 'error', }); } }; wichtige punkte zur like funktionalität optimistische updates wir aktualisieren die benutzeroberfläche sofort, bevor der server die änderung bestätigt das lässt die app reaktionsschneller erscheinen parse objekt updates wir holen den spezifischen beitrag mit query get(postid) wir ändern seine eigenschaften mit post set() wir speichern die änderungen mit post save() likes verfolgen wir führen sowohl eine zählung ( likes ) als auch eine liste von benutzern ( likedby ) das ermöglicht uns, genaue zählungen anzuzeigen und zu bestimmen, ob der aktuelle benutzer einen beitrag gemocht hat echtzeit updates mit livequery implementieren (optional) um das feed in echtzeit zu aktualisieren, wenn neue beiträge erstellt werden, können wir parse livequery verwenden // from feedpage js livequery setup const livequerysubscription = useref(null); useeffect(() => { // set up livequery for real time updates const setuplivequery = async () => { try { const post = parse object extend('post'); const query = new parse query(post); // subscribe to new posts livequerysubscription current = await query subscribe(); // when a new post is created livequerysubscription current on('create', (post) => { // only add to feed if it's not already there setposts(prevposts => { if (prevposts some(p => p id === post id)) return prevposts; const newpost = { id post id, content post get('content'), image post get('image') ? post get('image') url() null, likes post get('likes') || 0, likedby post get('likedby') || \[], createdat post get('createdat'), author { id post get('author') id, username post get('author') get('username'), avatar post get('author') get('avatar') ? post get('author') get('avatar') url() null } }; return \[newpost, prevposts]; }); }); // when a post is updated (e g , liked) livequerysubscription current on('update', (post) => { setposts(prevposts => prevposts map(p => p id === post id ? { p, content post get('content'), image post get('image') ? post get('image') url() p image, likes post get('likes') || 0, likedby post get('likedby') || \[] } p ) ); }); } catch (error) { console error('error setting up livequery ', error); } }; setuplivequery(); // clean up subscription when component unmounts return () => { if (livequerysubscription current) { livequerysubscription current unsubscribe(); } }; }, \[]); wichtige punkte zu livequery abonnement einrichten wir erstellen eine abfrage und abonnieren sie mit query subscribe() dies stellt eine websocket verbindung zum livequery server von back4app her ereignisbehandlung wir hören auf 'create' ereignisse, wenn neue beiträge erstellt werden wir hören auf 'update' ereignisse, wenn beiträge geändert werden wir aktualisieren unseren lokalen zustand entsprechend aufräumen wir kündigen unser abonnement, wenn die komponente unmontiert wird, um speicherlecks zu vermeiden optimierung des beitragsladens mit pagination wir haben bereits eine grundlegende pagination mit der schaltfläche "mehr laden" implementiert lassen sie uns dies mit unendlichem scrollen verbessern // from feedpage js infinite scrolling const \[isloadingmore, setisloadingmore] = usestate(false); const feedref = useref(null); // intersection observer for infinite scrolling useeffect(() => { if (!hasmore) return; const observer = new intersectionobserver( (entries) => { if (entries\[0] isintersecting && !isloading && !isloadingmore) { loadmoreposts(); } }, { threshold 0 5 } ); const loadmoretrigger = document getelementbyid('load more trigger'); if (loadmoretrigger) { observer observe(loadmoretrigger); } return () => { if (loadmoretrigger) { observer unobserve(loadmoretrigger); } }; }, \[hasmore, isloading, isloadingmore]); const loadmoreposts = async () => { if (!hasmore || isloadingmore) return; setisloadingmore(true); try { await fetchposts(true); } finally { setisloadingmore(false); } }; und füge dies am ende der beitragsliste hinzu {/ infinite scroll trigger /} {hasmore && ( \<box id="load more trigger" h="20px" /> )} wichtige punkte zum unendlichen scrollen intersection observer wir verwenden die intersection observer api, um zu erkennen, wann der benutzer zum ende scrollt wenn das auslösende element sichtbar wird, laden wir weitere beiträge ladezustände wir verfolgen separate ladezustände für den ersten ladevorgang und "mehr laden" dies verhindert mehrere gleichzeitige anfragen leistungsüberlegungen wir laden jeweils eine feste anzahl von beiträgen (seitenumbruch) wir überprüfen, ob es weitere beiträge zum laden gibt, bevor wir zusätzliche anfragen stellen back4app leistungsoptimierung um die leistung bei der arbeit mit back4app zu optimieren verwenden sie indizes fügen sie indizes zu häufig abgefragten feldern in ihrem back4app dashboard hinzu für die post klasse fügen sie indizes für 'createdat' und 'author' hinzu selektive abfragen verwenden sie query select() um nur die benötigten felder abzurufen dies reduziert den datentransfer und verbessert die leistung zähloptimierung anstatt alle beiträge abzurufen, um sie zu zählen, verwenden sie query count() dies ist effizienter zur bestimmung der gesamtanzahl schritt 6 — hinzufügen sozialer interaktionen in diesem schritt werden wir unser soziales netzwerk erweitern, indem wir wichtige funktionen für soziale interaktionen implementieren kommentare zu beiträgen, benutzerprofile und benutzereinstellungen wir werden uns darauf konzentrieren, wie diese funktionen mit dem back4app backend interagieren und die mechanismen, die sie zum funktionieren bringen kommentare zu beiträgen implementieren kommentare sind eine grundlegende funktion für soziale interaktionen, die eine ordnungsgemäße datenmodellierung in back4app erfordert lassen sie uns untersuchen, wie unsere anwendung mit dem parse server interagiert, um kommentare zu implementieren back4app datenmodell für kommentare in back4app werden kommentare als separate klasse mit beziehungen zu benutzern und beiträgen implementiert struktur der kommentar klasse inhalt (string) der textinhalt des kommentars autor (zeiger auf benutzer) zeigt auf den benutzer, der den kommentar erstellt hat beitrag (zeiger auf beitrag) zeigt auf den beitrag, zu dem kommentiert wird createdat (datum) automatisch von parse verwaltet beziehungstypen benutzer → kommentare eins zu viele (ein benutzer kann viele kommentare erstellen) beitrag → kommentare eins zu viele (ein beitrag kann viele kommentare haben) kommentare von back4app abrufen unsere postdetailspage verwendet parse abfragen, um kommentare für einen bestimmten beitrag abzurufen // from postdetailspage js comment fetching const fetchcomments = async () => { try { // create a query on the comment class const comment = parse object extend('comment'); const query = new parse query(comment); // find comments for this specific post using a pointer equality constraint query equalto('post', postobject); // include the author information query include('author'); // sort by creation date (newest first) query descending('createdat'); // execute the query const results = await query find(); // transform parse objects to plain objects for react state const commentslist = results map(comment => ({ id comment id, content comment get('content'), createdat comment get('createdat'), author { id comment get('author') id, username comment get('author') get('username'), avatar comment get('author') get('avatar') ? comment get('author') get('avatar') url() null } })); setcomments(commentslist); } catch (error) { console error('error fetching comments ', error); toaster create({ title 'error', description 'failed to load comments', type 'error', }); } }; wichtige back4app mechanismen parse object extend() erstellt eine referenz zur kommentar klasse in back4app query equalto() erstellt eine bedingung, um nur kommentare für einen bestimmten beitrag zu finden query include() führt eine join ähnliche operation durch, um verwandte objekte in einer einzigen abfrage abzurufen query descending() sortiert die ergebnisse nach einem bestimmten feld kommentare in back4app erstellen wenn ein benutzer einen kommentar hinzufügt, erstellen wir ein neues parse objekt und stellen die beziehungen her // from postdetailspage js adding a comment const handleaddcomment = async (e) => { e preventdefault(); if (!newcomment trim()) { return; } setiscommenting(true); try { // create a new comment object in back4app const comment = parse object extend('comment'); const comment = new comment(); // set comment data and relationships comment set('content', newcomment); comment set('author', parse user current()); // pointer to current user comment set('post', postobject); // pointer to current post // save the comment to back4app await comment save(); // clear the input setnewcomment(''); // refresh comments fetchcomments(); toaster create({ title 'success', description 'your comment has been added', type 'success', }); } catch (error) { toaster create({ title 'error', description error message, type 'error', }); } finally { setiscommenting(false); } }; wichtige back4app mechanismen new comment() erstellt eine neue instanz der kommentar klasse comment set() setzt eigenschaften des parse objekts, einschließlich zeigern auf verwandte objekte comment save() sendet das objekt an back4app zur speicherung parse user current() holt den aktuell authentifizierten benutzer, um die autorenbeziehung herzustellen back4app sicherheit für kommentare um kommentare in back4app richtig zu sichern konfigurieren sie die klassenberechtigungen (clps) lesen öffentlich (jeder kann kommentare lesen) schreiben nur authentifizierte benutzer (nur angemeldete benutzer können kommentieren) aktualisieren/löschen nur der ersteller (nur der kommentarautor kann ändern oder löschen) richten sie diese berechtigungen in ihrem back4app dashboard ein { "find" { " " true }, "get" { " " true }, "create" { " " true }, "update" { "requiresauthentication" true }, "delete" { "requiresauthentication" true }, "addfield" { "requiresauthentication" true } } schritt 7 benutzerprofile mit back4app erstellen benutzerprofile in unserer anwendung nutzen die integrierte benutzerklasse von parse mit benutzerdefinierten feldern lassen sie uns untersuchen, wie profilepage js mit back4app interagiert back4app benutzerklassen erweiterungen die parse benutzerklasse wird mit zusätzlichen feldern für unser soziales netzwerk erweitert benutzerdefinierte benutzerfelder avatar (datei) profilbild, das im dateispeicher von back4app gespeichert ist bio (string) benutzerbiografie website (string) url der benutzerwebsite displayname (string) anzeigename des benutzers benutzerdaten und beiträge abrufen unsere profilseite ruft sowohl benutzerdaten als auch die beiträge des benutzers ab // from profilepage js profile data fetching const fetchuserdata = async () => { try { // get current user from parse session const currentuser = await parse user current(); if (!currentuser) { navigate('/login'); return; } setuser(currentuser); // create a query to find posts by this user const post = parse object extend('post'); const query = new parse query(post); query equalto('author', currentuser); query include('author'); query descending('createdat'); const results = await query find(); // transform parse objects to plain objects const postslist = results map(post => ({ id post id, content post get('content'), image post get('image') ? post get('image') url() null, likes post get('likes') || 0, createdat post get('createdat'), author { id post get('author') id, username post get('author') get('username'), avatar post get('author') get('avatar') ? post get('author') get('avatar') url() null } })); setposts(postslist); setstats(prevstats => ({ prevstats, posts postslist length })); } catch (error) { console error('error fetching user data ', error); toaster create({ title 'error', description 'failed to load profile data', type 'error', }); } finally { setisloading(false); } }; wichtige back4app mechanismen parse user current() ruft den authentifizierten benutzer aus dem sitzungstoken ab query equalto('author', currentuser) erstellt eine zeiger gleichheitsbedingung, um beiträge des aktuellen benutzers zu finden post get('image') url() greift auf die url eines in back4app gespeicherten parse dateiobjekts zu benutzereinstellungen implementieren die einstellungen seite ermöglicht es benutzern, ihre profilinformationen zu aktualisieren und kontoeinstellungen zu verwalten lassen sie uns untersuchen, wie sie mit back4app interagiert // from settingspage js user settings implementation function settingspage() { const \[privacysettings, setprivacysettings] = usestate({ profilevisibility 'public', postprivacy 'friends' }); const \[twofactorauth, settwofactorauth] = usestate(false); const \[isopen, setisopen] = usestate(false); const cancelref = useref(); // save user settings to back4app const savesettings = async (settingstype, settingsdata) => { try { const currentuser = await parse user current(); if (!currentuser) { toaster create({ title 'error', description 'you must be logged in to save settings', type 'error', }); return; } // update the appropriate settings based on type switch (settingstype) { case 'privacy' currentuser set('privacysettings', settingsdata); break; case 'security' currentuser set('securitysettings', settingsdata); break; case 'notifications' currentuser set('notificationsettings', settingsdata); break; default break; } // save the user object await currentuser save(); toaster create({ title 'success', description 'your settings have been saved', type 'success', }); } catch (error) { toaster create({ title 'error', description error message, type 'error', }); } }; return ( \<box maxw="800px" mx="auto" p={4}> \<heading mb={6}>account settings\</heading> \<tabs root defaultvalue="profile"> \<tabs list> \<tabs trigger value="profile">profile\</tabs trigger> \<tabs trigger value="privacy">privacy\</tabs trigger> \<tabs trigger value="security">security\</tabs trigger> \<tabs trigger value="notifications">notifications\</tabs trigger> \<tabs indicator /> \</tabs list> {/ settings tabs content /} {/ /} \</tabs root> {/ account deactivation dialog /} \<dialog root open={isopen} onopenchange={setisopen}> {/ /} \</dialog root> \</box> ); } wichtige back4app mechanismen parse user current() ruft den aktuellen benutzer ab, um seine einstellungen zu aktualisieren currentuser set() aktualisiert die benutzereigenschaften im parse benutzerobjekt currentuser save() speichert die änderungen in back4app back4app benutzereinstellungen schema um einstellungen in back4app zu implementieren fügen sie diese felder zur benutzerklasse hinzu datenschutzeinstellungen (objekt) json objekt, das datenschutzpräferenzen enthält sicherheitseinstellungen (objekt) json objekt, das sicherheitseinstellungen enthält benachrichtigungseinstellungen (objekt) json objekt, das benachrichtigungspräferenzen enthält beispielschema für diese objekte // datenschutzeinstellungen { "profilsichtbarkeit" "öffentlich", // oder "freunde" oder "privat" "beitragsprivatsphäre" "freunde", // oder "öffentlich" oder "privat" "aktivitätanzeigen" true } // sicherheitseinstellungen { "zweifaktorauth" false, "anmeldewarnungen" true } // benachrichtigungseinstellungen { "likes" true, "kommentare" true, "folgen" true, "nachrichten" true } back4app cloud funktionen für soziale interaktionen für komplexere soziale interaktionen können sie cloud funktionen in back4app implementieren zum beispiel, um kommentarbenachrichtigungen zu verfolgen // example cloud function for comment notifications parse cloud aftersave("comment", async (request) => { // only run for new comments, not updates if (request original) return; const comment = request object; const post = comment get("post"); const commenter = request user; // skip if user is commenting on their own post const postquery = new parse query("post"); const fullpost = await postquery get(post id, { usemasterkey true }); const postauthor = fullpost get("author"); if (postauthor id === commenter id) return; // create a notification const notification = parse object extend("notification"); const notification = new notification(); notification set("type", "comment"); notification set("fromuser", commenter); notification set("touser", postauthor); notification set("post", post); notification set("read", false); await notification save(null, { usemasterkey true }); }); um dies zu implementieren gehe zu deinem back4app dashboard navigiere zu "cloud code" > "cloud functions" erstelle eine neue funktion mit dem obigen code setze die funktion ein schritt 8 — echtzeit messaging aufbauen in diesem schritt werden wir die echtzeit messaging funktionalität mit der livequery funktion von back4app implementieren dies ermöglicht es den benutzern, nachrichten sofort auszutauschen, ohne die seite zu aktualisieren, und schafft ein dynamisches chat erlebnis, das beliebten messaging plattformen ähnelt verstehen von back4app livequery bevor wir in die implementierung eintauchen, lassen sie uns verstehen, wie back4app's livequery funktioniert was ist livequery? livequery ist eine funktion des parse servers, die es clients ermöglicht, sich für abfragen anzumelden wenn objekte, die diesen abfragen entsprechen, sich ändern, sendet der server automatisch updates an abonnierte clients dies schafft echtzeitfunktionalität, ohne dass sie selbst komplexe websocket verwaltung implementieren müssen wie livequery funktioniert livequery stellt eine websocket verbindung zwischen dem client und dem server her kunden abonnieren spezifische abfragen, die sie überwachen möchten wenn die daten, die diesen abfragen entsprechen, sich ändern, sendet der server ereignisse über das websocket der kunde erhält diese ereignisse und aktualisiert die benutzeroberfläche entsprechend livequery ereignisse erstellen ausgelöst, wenn ein neues objekt, das der abfrage entspricht, erstellt wird aktualisieren ausgelöst, wenn ein vorhandenes objekt, das der abfrage entspricht, aktualisiert wird eingeben ausgelöst, wenn ein objekt beginnt, die abfrage zu erfüllen verlassen ausgelöst, wenn ein objekt nicht mehr mit der abfrage übereinstimmt löschen ausgelöst, wenn ein objekt, das der abfrage entspricht, gelöscht wird einrichten von livequery in back4app um livequery für ihre anwendung zu aktivieren, befolgen sie diese schritte aktivieren sie ihre back4app subdomain melden sie sich bei ihrem back4app konto an navigieren sie zu "app einstellungen" > "servereinstellungen" finden sie den block "server url und live abfrage" und klicken sie auf "einstellungen" überprüfen sie die option "aktivieren sie ihre back4app subdomain" diese subdomain wird als ihr livequery server dienen livequery aktivieren auf derselben einstellungsseite aktivieren sie die option "live abfrage aktivieren" wählen sie die klassen aus, die sie mit livequery überwachen möchten nachricht (für chat nachrichten) tippstatus (für tippindikatoren) gespräch (für gesprächsaktualisierungen) ändern sie ihre änderungen notieren sie ihre livequery server url ihre livequery server url hat das format wss\ //yourappname back4app io sie benötigen diese url, um den livequery client in ihrer react anwendung zu initialisieren livequery in ihrer react app konfigurieren um livequery in ihrer react anwendung zu verwenden, müssen sie einen livequery client initialisieren // from parseconfig js or app js parse initialize( process env react app parse app id, process env react app parse js key ); parse serverurl = process env react app parse server url; // initialize live queries with your subdomain parse livequeryserverurl = process env react app parse live query url; // e g , 'wss\ //yourappname back4app io' in deiner env local datei, stelle sicher, dass du folgendes einfügst react app parse live query url=wss\ //yourappname back4app io erstellen des datenmodells für messaging unser nachrichtensystem benötigt zwei hauptklassen in back4app gesprächsklasse teilnehmer (array) array von benutzerzeigern für die benutzer im gespräch letztenachricht (string) der inhalt der letzten nachricht letztenachrichtdatum (datum) zeitstempel der letzten nachricht aktualisiertam (datum) automatisch verwaltet von parse nachricht klasse gespräch (zeiger) zeigt auf das gespräch, zu dem diese nachricht gehört absender (zeiger) zeigt auf den benutzer, der die nachricht gesendet hat inhalt (string) der textinhalt der nachricht lesen (boolean) ob die nachricht gelesen wurde erstelltam (datum) automatisch verwaltet von parse typingstatus klasse gespräch (zeiger) zeigt auf das gespräch benutzer (zeiger) zeigt auf den benutzer, der tippt tippt gerade (boolean) ob der benutzer gerade tippt implementierung der messaging schnittstelle lass uns untersuchen, wie unsere messagespage echtzeit nachrichten implementiert // from messagespage js component structure function messagespage() { const \[conversations, setconversations] = usestate(\[]); const \[selectedconversation, setselectedconversation] = usestate(null); const \[messages, setmessages] = usestate(\[]); const \[newmessage, setnewmessage] = usestate(''); const \[isloading, setisloading] = usestate(true); const \[typingusers, settypingusers] = usestate(\[]); const messagesendref = useref(null); const messagesubscription = useref(null); const typingsubscription = useref(null); const conversationsubscription = useref(null); const typingtimeoutref = useref(null); // rest of the component } die komponente verwaltet mehrere zustände conversations liste der gespräche des benutzers selectedconversation das aktuell ausgewählte gespräch messages nachrichten im ausgewählten gespräch typingusers benutzer, die gerade im gespräch tippen es verwendet auch refs, um livequery abonnements zu speichern und tippindikatoren zu verwalten abonnieren von livequery für nachrichten der schlüssel zur echtzeitkommunikation besteht darin, sich für livequery für nachrichten im aktuellen gespräch anzumelden // from messagespage js livequery subscription for messages const subscribetomessages = async (conversation) => { try { // unsubscribe from previous subscription if exists if (messagesubscription current) { messagesubscription current unsubscribe(); } // create a query for messages in this conversation const message = parse object extend('message'); const query = new parse query(message); // create a pointer to the conversation const conversation = parse object extend('conversation'); const conversationpointer = new conversation(); conversationpointer id = conversation id; // find messages for this conversation query equalto('conversation', conversationpointer); // include the sender information query include('sender'); // subscribe to the query const subscription = await query subscribe(); messagesubscription current = subscription; // when a new message is created subscription on('create', (message) => { // add the new message to our state setmessages(prevmessages => { // check if message already exists in our list const exists = prevmessages some(m => m id === message id); if (exists) return prevmessages; // add the new message return \[ prevmessages, { id message id, content message get('content'), createdat message get('createdat'), sender { id message get('sender') id, username message get('sender') get('username'), avatar message get('sender') get('avatar') ? message get('sender') get('avatar') url() null }, read message get('read') }]; }); // scroll to bottom when new message arrives scrolltobottom(); // mark message as read if from other user if (message get('sender') id !== parse user current() id) { markmessageasread(message); } }); } catch (error) { console error('error subscribing to messages ', error); } }; wichtige livequery mechanismen eine abfrage erstellen wir erstellen eine abfrage für nachrichten im aktuellen gespräch abonnieren der abfrage wir rufen query subscribe() auf, um änderungen zu hören ereignisse behandeln wir verwenden subscription on('create', callback) um neue nachrichten zu behandeln abbestellen wir speichern die abonnementreferenz und kündigen bei bedarf implementierung von tippindikatoren mit livequery tippindikatoren sind ein weiteres echtzeit feature, das mit livequery implementiert wurde // from messagespage js livequery for typing indicators const subscribetotypingstatus = async (conversation) => { try { // unsubscribe from previous subscription if exists if (typingsubscription current) { typingsubscription current unsubscribe(); } // create a query for typing status in this conversation const typingstatus = parse object extend('typingstatus'); const query = new parse query(typingstatus); // create a pointer to the conversation const conversation = parse object extend('conversation'); const conversationpointer = new conversation(); conversationpointer id = conversation id; // find typing status for this conversation query equalto('conversation', conversationpointer); // include the user information query include('user'); // subscribe to the query const subscription = await query subscribe(); typingsubscription current = subscription; // when a typing status is updated subscription on('update', (typingstatus) => { const user = typingstatus get('user'); const istyping = typingstatus get('istyping'); // update typing users list settypingusers(prevtypingusers => { // if user is typing, add them to the list if (istyping) { // check if user is already in the list const exists = prevtypingusers some(u => u id === user id); if (exists) return prevtypingusers; // add user to typing list return \[ prevtypingusers, { id user id, username user get('username') }]; } else { // if user stopped typing, remove them from the list return prevtypingusers filter(u => u id !== user id); } }); }); // when a new typing status is created subscription on('create', (typingstatus) => { const user = typingstatus get('user'); const istyping = typingstatus get('istyping'); // only add to typing users if they are actually typing if (istyping && user id !== parse user current() id) { settypingusers(prevtypingusers => { // check if user is already in the list const exists = prevtypingusers some(u => u id === user id); if (exists) return prevtypingusers; // add user to typing list return \[ prevtypingusers, { id user id, username user get('username') }]; }); } }); } catch (error) { console error('error subscribing to typing status ', error); } }; aktualisierung des tippstatus wenn ein benutzer tippt, aktualisieren wir seinen tippstatus // from messagespage js updating typing status const updatetypingstatus = async (istyping) => { if (!selectedconversation) return; try { const currentuser = await parse user current(); // create a pointer to the conversation const conversation = parse object extend('conversation'); const conversationpointer = new conversation(); conversationpointer id = selectedconversation id; // check if a typing status already exists const typingstatus = parse object extend('typingstatus'); const query = new parse query(typingstatus); query equalto('conversation', conversationpointer); query equalto('user', currentuser); let typingstatus = await query first(); if (typingstatus) { // update existing typing status typingstatus set('istyping', istyping); } else { // create new typing status typingstatus = new typingstatus(); typingstatus set('conversation', conversationpointer); typingstatus set('user', currentuser); typingstatus set('istyping', istyping); } await typingstatus save(); } catch (error) { console error('error updating typing status ', error); } }; // handle typing indicator with debounce const handletyping = () => { updatetypingstatus(true); // clear previous timeout if (typingtimeoutref current) { cleartimeout(typingtimeoutref current); } // set typing to false after 3 seconds of inactivity typingtimeoutref current = settimeout(() => { updatetypingstatus(false); }, 3000); }; nachrichten senden beim senden von nachrichten erstellen wir ein neues nachrichtenobjekt und lassen livequery die aktualisierungen übernehmen // from messagespage js sending messages const sendmessage = async (e) => { e preventdefault(); if (!newmessage trim() || !selectedconversation) return; try { const currentuser = await parse user current(); // create a pointer to the conversation const conversation = parse object extend('conversation'); const conversationpointer = new conversation(); conversationpointer id = selectedconversation id; // create a new message const message = parse object extend('message'); const message = new message(); message set('content', newmessage); message set('sender', currentuser); message set('conversation', conversationpointer); message set('read', false); await message save(); // update the conversation with the last message const conversation = await new parse query(conversation) get(selectedconversation id); conversation set('lastmessage', newmessage); conversation set('lastmessagedate', new date()); await conversation save(); // clear the input setnewmessage(''); // set typing status to false updatetypingstatus(false); } catch (error) { console error('error sending message ', error); toast({ title 'error', description 'failed to send message', status 'error', duration 3000, isclosable true, }); } }; bereinigung von livequery abonnements es ist wichtig, livequery abonnements zu bereinigen, wenn sie nicht mehr benötigt werden // from messagespage js cleanup useeffect(() => { // fetch initial conversations fetchconversations(); subscribetoconversations(); // cleanup subscriptions when component unmounts return () => { if (messagesubscription current) { messagesubscription current unsubscribe(); } if (typingsubscription current) { typingsubscription current unsubscribe(); } if (conversationsubscription current) { conversationsubscription current unsubscribe(); } if (typingtimeoutref current) { cleartimeout(typingtimeoutref current); } }; }, \[]); back4app livequery leistungsüberlegungen bei der implementierung von livequery sollten sie diese leistungstipps beachten seien sie spezifisch mit anfragen abonnieren sie nur die daten, die sie benötigen verwenden sie einschränkungen, um den umfang der abonnements zu begrenzen zum beispiel, abonnieren sie nur nachrichten im aktuellen gespräch verwalten sie abonnements sorgfältig abbestellen, wenn daten nicht mehr benötigt werden erstellen sie neue abonnements, wenn sich der kontext ändert speichern sie abonnementreferenzen, um später abzubestellen verwenden sie acls für sicherheit setzen sie geeignete acls auf nachrichten und gesprächsobjekte stellen sie sicher, dass benutzer nur auf gespräche zugreifen können, an denen sie teilnehmen livequery respektiert acls, sodass unbefugte benutzer keine updates erhalten optimieren sie den livequery server konfigurieren sie im back4app dashboard die klassen, die livequery benötigen aktivieren sie livequery nicht für klassen, die keine echtzeit updates benötigen schritt 9 — implementierung der suchfunktionalität in diesem schritt werden wir eine umfassende suchfunktionalität für unser soziales netzwerk implementieren benutzer werden in der lage sein, nach anderen benutzern, beiträgen nach inhalt und hashtags zu suchen diese funktion wird es den benutzern erleichtern, inhalte zu entdecken und sich mit anderen auf der plattform zu verbinden verstehen der suche in back4app bevor wir in die implementierung eintauchen, lassen sie uns verstehen, wie die suche in back4app funktioniert parse abfragesystem back4app verwendet das abfragesystem von parse server zur suche abfragen können über mehrere klassen hinweg durchgeführt werden sie können nach exakter übereinstimmung, enthält, beginnt mit usw suchen textsuchoptionen beginntmit findet zeichenfolgen, die mit einer bestimmten zeichenfolge beginnen enthält findet zeichenfolgen, die eine bestimmte teilzeichenfolge enthalten entspricht verwendet reguläre ausdrücke für komplexere musterabgleiche volltext (enterprise funktion) bietet erweiterte volltextsuchfunktionen leistungsüberlegungen textsuche kann ressourcenintensiv sein indizes sollten für häufig gesuchte felder erstellt werden abfragen sollten optimiert werden, um die anzahl der ergebnisse zu begrenzen erstellen der suchseite unsere searchpage komponente wird verschiedene arten von suchen behandeln und die ergebnisse anzeigen lassen sie uns ihre struktur untersuchen // from searchpage js component structure function searchpage() { const \[searchquery, setsearchquery] = usestate(''); const \[searchtype, setsearchtype] = usestate('users'); // 'users', 'posts', 'hashtags' const \[searchresults, setsearchresults] = usestate(\[]); const \[isloading, setisloading] = usestate(false); const \[trendingtopics, settrendingtopics] = usestate(\[]); // rest of the component } die komponente verwaltet den zustand für die suchanfrage, die vom benutzer eingegeben wurde die art der durchgeführten suche die suchergebnisse ladezustand trendthemen benutzersuche implementieren schauen wir uns an, wie wir benutzer in back4app suchen // from searchpage js user search implementation const searchusers = async (query) => { setisloading(true); try { // create a query on the user class const userquery = new parse query(parse user); // search for usernames that contain the query string (case insensitive) userquery matches('username', new regexp(query, 'i')); // limit results to improve performance userquery limit(20); const users = await userquery find(); // transform parse objects to plain objects const userresults = users map(user => ({ id user id, username user get('username'), avatar user get('avatar') ? user get('avatar') url() null, bio user get('bio') || '' })); setsearchresults(userresults); } catch (error) { console error('error searching users ', error); toaster create({ title 'error', description 'failed to search users', type 'error', }); } finally { setisloading(false); } }; wichtige back4app mechanismen new parse query(parse user) erstellt eine abfrage auf der benutzerklasse userquery matches('username', new regexp(query, 'i')) führt einen nicht groß /kleinschreibungsempfindlichen regex abgleich auf benutzernamen durch userquery limit(20) begrenzung der ergebnisse zur verbesserung der leistung userquery find() führt die abfrage aus und gibt übereinstimmende benutzer zurück implementierung der postsuchfunktion nach inhalt jetzt schauen wir uns an, wie wir nach inhalten in posts suchen // from searchpage js post search implementation const searchposts = async (query) => { setisloading(true); try { // create a query on the post class const post = parse object extend('post'); const postquery = new parse query(post); // search for posts with content containing the query string postquery matches('content', new regexp(query, 'i')); // include the author information postquery include('author'); // sort by creation date (newest first) postquery descending('createdat'); // limit results postquery limit(20); const posts = await postquery find(); // transform parse objects to plain objects const postresults = posts map(post => ({ id post id, content post get('content'), image post get('image') ? post get('image') url() null, likes post get('likes') || 0, createdat post get('createdat'), author { id post get('author') id, username post get('author') get('username'), avatar post get('author') get('avatar') ? post get('author') get('avatar') url() null } })); setsearchresults(postresults); } catch (error) { console error('error searching posts ', error); toaster create({ title 'error', description 'failed to search posts', type 'error', }); } finally { setisloading(false); } }; wichtige back4app mechanismen parse object extend('post') verweist auf die post klasse postquery matches('content', new regexp(query, 'i')) führt einen fallunempfindlichen regex abgleich auf den post inhalten durch postquery include('author') schließt die autoreninformationen in einer einzigen abfrage ein postquery descending('createdat') sortiert die ergebnisse nach erstellungsdatum implementierung der hashtag suche die hashtag suche erfordert einen anderen ansatz wir suchen nach beiträgen, die hashtags enthalten // from searchpage js hashtag search implementation const searchhashtags = async (query) => { setisloading(true); try { // remove # if present at the beginning const hashtagquery = query startswith('#') ? query substring(1) query; // create a query on the post class const post = parse object extend('post'); const postquery = new parse query(post); // search for posts with content containing the hashtag // we use word boundaries to find actual hashtags postquery matches('content', new regexp(`#${hashtagquery}\\\b`, 'i')); // include the author information postquery include('author'); // sort by creation date (newest first) postquery descending('createdat'); // limit results postquery limit(20); const posts = await postquery find(); // transform parse objects to plain objects const hashtagresults = posts map(post => ({ id post id, content post get('content'), image post get('image') ? post get('image') url() null, likes post get('likes') || 0, createdat post get('createdat'), author { id post get('author') id, username post get('author') get('username'), avatar post get('author') get('avatar') ? post get('author') get('avatar') url() null } })); setsearchresults(hashtagresults); } catch (error) { console error('error searching hashtags ', error); toaster create({ title 'error', description 'failed to search hashtags', type 'error', }); } finally { setisloading(false); } }; wichtige back4app mechanismen wir verwenden einen regex mit wortgrenzen ( \\\b ) um tatsächliche hashtags zu finden dieser ansatz findet beiträge, in denen der inhalt den spezifischen hashtag enthält implementierung von trending topics um trending topics zu implementieren, müssen wir aktuelle beiträge analysieren und die hashtag vorkommen zählen // from searchpage js fetching trending topics const fetchtrendingtopics = async () => { try { // create a query on the post class const post = parse object extend('post'); const query = new parse query(post); // get posts from the last 7 days const oneweekago = new date(); oneweekago setdate(oneweekago getdate() 7); query greaterthan('createdat', oneweekago); // limit to a reasonable number for analysis query limit(500); const posts = await query find(); // extract hashtags from post content const hashtagcounts = {}; posts foreach(post => { const content = post get('content') || ''; // find all hashtags in the content const hashtags = content match(/#(\w+)/g) || \[]; // count occurrences of each hashtag hashtags foreach(hashtag => { const tag = hashtag tolowercase(); hashtagcounts\[tag] = (hashtagcounts\[tag] || 0) + 1; }); }); // convert to array and sort by count const trendingarray = object entries(hashtagcounts) map((\[hashtag, count]) => ({ hashtag, count })) sort((a, b) => b count a count) slice(0, 10); // get top 10 settrendingtopics(trendingarray); } catch (error) { console error('error fetching trending topics ', error); } }; wichtige back4app mechanismen wir fragen beiträge der letzten 7 tage ab mit query greaterthan('createdat', oneweekago) wir analysieren den inhalt, um hashtags zu extrahieren und zu zählen wir sortieren nach häufigkeit, um die beliebtesten hashtags zu finden verarbeitung der suchausführung schauen wir uns nun an, wie wir die suchausführung basierend auf dem suchtyp handhaben // from searchpage js search execution const handlesearch = (e) => { e preventdefault(); if (!searchquery trim()) return; switch (searchtype) { case 'users' searchusers(searchquery); break; case 'posts' searchposts(searchquery); break; case 'hashtags' searchhashtags(searchquery); break; default searchusers(searchquery); } }; optimierung der suche in back4app um die suchleistung in back4app zu optimieren indizes erstellen navigiere zu deinem back4app dashboard gehe zu "datenbank browser" > wähle die klasse (z b benutzer, beitrag) klicke auf den tab "indizes" erstelle indizes für häufig durchsuchte felder für die benutzerklasse erstelle einen index auf benutzername für die beitragsklasse erstelle einen index auf inhalt verwende abfragebeschränkungen verwende immer limit() um die anzahl der ergebnisse zu beschränken verwende select() um nur die benötigten felder abzurufen verwende skip() für die paginierung bei großen ergebnismengen berücksichtige cloud funktionen für komplexe suchen für komplexere suchlogik implementiere eine cloud funktion dies ermöglicht es dir, serverseitige verarbeitung durchzuführen und optimierte ergebnisse zurückzugeben beispiel cloud funktion für erweiterte suche // example cloud function for advanced search parse cloud define("advancedsearch", async (request) => { const { query, type, limit = 20 } = request params; if (!query) { throw new error("search query is required"); } let results = \[]; switch (type) { case 'users' const userquery = new parse query(parse user); userquery matches('username', new regexp(query, 'i')); userquery limit(limit); results = await userquery find({ usemasterkey true }); break; case 'posts' const post = parse object extend('post'); const postquery = new parse query(post); postquery matches('content', new regexp(query, 'i')); postquery include('author'); postquery limit(limit); results = await postquery find({ usemasterkey true }); break; // add more search types as needed default throw new error("invalid search type"); } return results; }); schritt 10 — testen und bereitstellen ihres sozialen netzwerks in diesem letzten schritt werden wir behandeln, wie sie ihre anwendung testen, sie für die produktion vorbereiten, sie auf einen hosting service bereitstellen und ihr back4app backend überwachen und skalieren diese schritte sind entscheidend, um sicherzustellen, dass ihr soziales netzwerk in einer produktionsumgebung reibungslos läuft testen ihrer anwendung vor der bereitstellung ist es wichtig, ihre anwendung gründlich zu testen, um fehler oder probleme zu erkennen 1\ manuelle tests erstellen sie einen testplan, der alle wichtigen funktionen ihrer anwendung abdeckt benutzerauthentifizierung testregistrierung mit gültigen und ungültigen eingaben testanmeldung mit richtigen und falschen anmeldeinformationen testen der passwortzurücksetzfunktionalität testen der sitzungsbeständigkeit und abmeldung beitragsfunktionalität testen sie das erstellen von beiträgen mit text und bildern testanzeige von beiträgen im feed testen von likes und kommentaren zu beiträgen test das löschen von beiträgen soziale interaktionen testansicht von benutzerprofilen testkommentierung zu beiträgen echtzeit nachrichten testen suchfunktionalität testsuche nach benutzern testsuche nach beiträgen test hashtag suche cross browser test testen sie auf chrome, firefox, safari und edge test auf mobilen browsern 2\ automatisierte tests für robustere tests automatisierte tests implementieren // example jest test for the login component import react from 'react'; import { render, fireevent, waitfor } from '@testing library/react'; import loginpage from ' /src/pages/loginpage'; import parse from 'parse/dist/parse min js'; // mock parse jest mock('parse/dist/parse min js', () => ({ user { login jest fn() } })); test('login form submits with username and password', async () => { parse user login mockresolvedvalueonce({ id '123', get () => 'testuser' }); const { getbylabeltext, getbyrole } = render(\<loginpage />); // fill in the form fireevent change(getbylabeltext(/username/i), { target { value 'testuser' } }); fireevent change(getbylabeltext(/password/i), { target { value 'password123' } }); // submit the form fireevent click(getbyrole('button', { name /log in/i })); // check if parse user login was called with correct arguments await waitfor(() => { expect(parse user login) tohavebeencalledwith('testuser', 'password123'); }); }); 3\ back4app testen testen sie ihre back4app konfiguration cloud funktionen testen sie alle cloud funktionen mit verschiedenen eingaben sicherheit überprüfen sie, ob ihre klassenberechtigungen korrekt funktionieren livequery testen sie die echtzeitfunktionalität mit mehreren clients vorbereitung auf die produktion optimieren sie ihre anwendung vor der bereitstellung für die produktion 1\ umgebungs konfiguration erstellen sie separate umgebungsdateien für entwicklung und produktion \# env development react app parse app id=your dev app id react app parse js key=your dev js key react app parse server url=https //parseapi back4app com react app parse live query url=wss\ //your dev app back4app io \# env production react app parse app id=your production app id react app parse js key=your production js key react app parse server url=https //parseapi back4app com react app parse live query url=wss\ //your prod app back4app io 2\ build optimierung optimieren sie ihren react build // in your package json "scripts" { "analyze" "source map explorer 'build/static/js/ js'", "build" "generate sourcemap=false react scripts build" } installieren sie den source map explorer, um die größe ihres bundles zu analysieren npm install save dev source map explorer 3\ leistungsoptimierung implementieren sie code splitting, um die ladezeit zu reduzieren // in app js, use react lazy for route components import react, { suspense, lazy } from 'react'; import { browserrouter as router, routes, route } from 'react router dom'; import { chakraprovider } from '@chakra ui/react'; import loadingspinner from ' /components/loadingspinner'; // lazy load pages const landingpage = lazy(() => import(' /pages/landingpage')); const loginpage = lazy(() => import(' /pages/loginpage')); const feedpage = lazy(() => import(' /pages/feedpage')); // other pages function app() { return ( \<chakraprovider> \<router> \<suspense fallback={\<loadingspinner />}> \<routes> \<route path="/" element={\<landingpage />} /> \<route path="/login" element={\<loginpage />} /> \<route path="/feed" element={\<feedpage />} /> {/ other routes /} \</routes> \</suspense> \</router> \</chakraprovider> ); } bereitstellung bei einem hosting dienst es gibt mehrere optionen zur bereitstellung ihrer react anwendung 1\ bereitstellung bei vercel vercel ist eine großartige option für react anwendungen installieren sie die vercel cli npm install g vercel deployen sie ihre anwendung vercel für die produktionsbereitstellung vercel prod 2\ bereitstellung auf netlify netlify ist eine weitere ausgezeichnete option installieren sie die netlify cli npm install g netlify cli bauen sie ihre anwendung npm run build bereitstellen auf netlify netlify deploy für die produktionsbereitstellung netlify deploy prod 3\ bereitstellung auf github pages für eine einfache bereitstellungsoption installiere gh pages npm install save dev gh pages füge zu package json hinzu "homepage" "https //yourusername github io/your repo name", "scripts" { "predeploy" "npm run build", "deploy" "gh pages d build" } bereitstellen npm run deploy überwachung und skalierung ihres back4app backends wenn ihr soziales netzwerk wächst, müssen sie ihr back4app backend überwachen und skalieren 1\ überwachung der leistung back4app bietet mehrere tools zur überwachung ihrer anwendung dashboard analytik überwachen sie api anfragen, speichernutzung und dateioperationen protokolle überprüfen sie die serverprotokolle auf fehler und leistungsprobleme leistungskennzahlen reaktionszeiten verfolgen und engpässe identifizieren um auf diese tools zuzugreifen gehen sie zu ihrem back4app dashboard navigieren sie zu "analytik" für nutzungsstatistiken überprüfen sie "protokolle" für detaillierte betriebsprotokolle 2\ skalierung ihres backends wenn ihre benutzerbasis wächst, müssen sie möglicherweise ihr back4app backend skalieren upgrade ihres plans wechseln sie zu einem höheren tarif mit mehr ressourcen abfragen optimieren verwenden sie indizes und beschränken sie abfragen, um die leistung zu verbessern caching implementieren verwenden sie clientseitiges caching für häufig abgerufene daten 3\ datenbankoptimierung optimieren sie ihre datenbank für bessere leistung indizes erstellen fügen sie indizes zu häufig abgefragten feldern hinzu // beispiel erstellen eines index auf dem 'benutzernamen' feld in der benutzerklasse const schema = new parse schema(' user'); schema addindex('username index', { username 1 }); schema update(); aggregation pipeline verwenden für komplexe datenoperationen // beispiel beiträge nach benutzer zählen const pipeline = \[ { group { objectid '$author', count { $sum 1 } } } ]; const results = await parse cloud aggregate('post', pipeline); 4\ implementierung eines cdn für medien für schnellere bereitstellung von bildern und medien konfigurieren sie ein cdn wie cloudflare oder amazon cloudfront aktualisieren sie ihre back4app dateispeichereinstellungen, um das cdn zu verwenden aktualisieren sie die datei urls in ihrer anwendung, um die cdn domain zu verwenden 5\ einrichtung von überwachungsbenachrichtigungen richten sie benachrichtigungen ein, um über probleme informiert zu werden gehen sie zu ihrem back4app dashboard navigieren sie zu "app einstellungen" > "benachrichtigungen" konfigurieren sie benachrichtigungen für hohe api nutzung spitzen bei der fehlerquote datenbankgrößenbeschränkungen serverausfallzeiten zusammenfassung dessen, was erreicht wurde im laufe dieses tutorials haben sie richten sie eine robuste backend infrastruktur ein ein back4app konto erstellt und ihre anwendung konfiguriert ein datenbankschema für benutzer, beiträge, kommentare und nachrichten entworfen konfigurierte sicherheitseinstellungen und klassenebene berechtigungen livequery für echtzeitfunktionen einrichten ein modernes react frontend gebaut eine responsive benutzeroberfläche mit chakra ui komponenten erstellt client seitiges routing mit react router implementiert entwickelte wiederverwendbare komponenten für beiträge, kommentare und benutzerprofile verbinden sie ihr frontend mit back4app über das parse javascript sdk implementierte grundlegende funktionen des sozialen netzwerks benutzerauthentifizierung (registrierung, anmeldung, passwort zurücksetzen) beitragserstellung und interaktion (likes, kommentare) benutzerprofile und einstellungen echtzeit nachrichten zwischen benutzern suchfunktion für benutzer, beiträge und hashtags für die produktion optimiert implementierte leistungsoptimierungen wie code splitting umgebungskonfigurationen für entwicklung und produktion einrichten gelernt, wie man ihre anwendung auf hosting dienste bereitstellt untersuchte überwachungs und skalierungsstrategien für dein back4app backend sie haben jetzt eine solide grundlage für eine social network anwendung, die erweitert und angepasst werden kann, um ihren spezifischen bedürfnissen gerecht zu werden nächste schritte zur erweiterung der anwendung hier sind einige spannende möglichkeiten, um ihre social network anwendung zu verbessern erweiterte medienfunktionen unterstützung für video uploads und wiedergabe hinzufügen bildfilter und bearbeitungswerkzeuge implementieren erstellen sie geschichten oder vergängliche inhaltsfunktionen unterstützung für gifs und andere reichhaltige medien hinzufügen verbesserte soziale interaktionen implementieren sie eine empfehlungsmaschine für freundschaftsvorschläge gruppen oder gemeinschaftsfunktionalität hinzufügen veranstaltungen mit rsvp funktionen erstellen entwickeln sie ein benachrichtigungssystem für alle benutzerinteraktionen monetarisierungsoptionen premium mitgliedschaftsfunktionen implementieren in app käufe für digitale waren hinzufügen einen marktplatz für transaktionen zwischen nutzern erstellen integrieren sie sich mit zahlungsanbietern wie stripe mobile erfahrung konvertieren sie ihre anwendung in eine progressive web app (pwa) entwickeln sie native mobile apps mit react native implementieren sie push benachrichtigungen für mobile geräte optimieren sie die benutzeroberfläche für verschiedene bildschirmgrößen und orientierungen analytik und einblicke analytik tools integrieren, um das nutzerengagement zu verfolgen dashboards für die inhaltsleistung erstellen a/b tests für neue funktionen implementieren entwickeln sie einblicke in das nutzerverhalten, um die plattform zu verbessern inhaltsmoderation automatisierte inhaltsfilterung implementieren erstellen sie berichtssysteme für unangemessene inhalte entwickeln sie admin tools zur inhaltsmoderation verwenden sie maschinelles lernen für intelligente inhaltsanalyse zusätzliche ressourcen zum lernen um ihr wissen und ihre fähigkeiten weiter auszubauen, finden sie hier einige wertvolle ressourcen back4app dokumentation und tutorials back4app dokumentation https //www back4app com/docs/get started/welcome parse javascript anleitung https //docs parseplatform org/js/guide/ back4app youtube kanal https //www youtube com/c/back4app react und modernes javascript react dokumentation https //reactjs org/docs/getting started html javascript info https //javascript info/ egghead io react kurse https //egghead io/q/react ui und ux design chakra ui dokumentation https //chakra ui com/docs/getting started ui designmuster https //ui patterns com/ nielsen norman gruppe ux forschung https //www nngroup com/articles/ leistungsoptimierung web dev leistung https //web dev/performance scoring/ react leistungsoptimierung https //reactjs org/docs/optimizing performance html google pagespeed insights https //developers google com/speed/pagespeed/insights/ gemeinschaft und unterstützung stack overflow https //stackoverflow\ com/questions/tagged/parse platform parse community forum https //community parseplatform org/ react dev community https //dev to/t/react denken sie daran, dass der aufbau eines erfolgreichen sozialen netzwerks ein iterativer prozess ist beginnen sie mit einer soliden grundlage (die sie jetzt haben), sammeln sie benutzerfeedback und verbessern sie ihre anwendung kontinuierlich basierend auf realen nutzungsmustern wir hoffen, dass dieses tutorial ihnen das wissen und das vertrauen vermittelt hat, um erstaunliche anwendungen mit react und back4app zu erstellen viel spaß beim programmieren