Project Templates
Social Network
Comment créer un réseau social avec React
125 min
introduction dans ce tutoriel, vous allez construire back4gram, une plateforme de réseau social complète similaire à instagram back4gram permet aux utilisateurs de créer des comptes, de partager des publications avec des images, d'interagir par le biais de likes et de commentaires, de rechercher du contenu et de communiquer via des messages en temps réel ce projet démontre comment combiner les puissantes capacités frontend de react avec les robustes services backend de back4app pour créer une application sociale moderne et riche en fonctionnalités react est le choix parfait pour le frontend d'un réseau social en raison de son architecture basée sur des composants, qui permet des éléments d'interface utilisateur réutilisables et un rendu efficace pendant ce temps, back4app fournit un backend parse server géré qui gère l'authentification des utilisateurs, le stockage des données, les téléchargements de fichiers et les fonctionnalités en temps réel sans nécessiter que vous construisiez une infrastructure serveur complexe à partir de zéro en complétant ce tutoriel, vous construirez un réseau social complet avec authentification utilisateur (inscription, connexion, réinitialisation de mot de passe) gestion de profil création de publications avec téléchargements d'images interactions sociales (j'aime, commentaires) messagerie en temps réel avec indicateurs de saisie fonctionnalité de recherche de contenu paramètres et préférences utilisateur en cours de route, vous acquerrez des compétences précieuses dans développement react avec hooks et contextes développement ui avec chakra ui intégration de parse server via back4app gestion des données en temps réel avec livequery flux d'authentification utilisateur gestion des téléchargements de fichiers mise en œuvre de design réactif que vous cherchiez à lancer votre propre plateforme sociale ou que vous souhaitiez simplement comprendre comment les réseaux sociaux modernes sont construits, ce tutoriel vous fournira les connaissances et l'expérience pratique nécessaires pour atteindre vos objectifs à tout moment, vous pouvez accéder au code complet sur github prérequis pour compléter ce tutoriel, vous aurez besoin de un compte back4app inscrivez vous pour un compte gratuit sur back4app com https //www back4app com/ vous utiliserez cela pour créer et gérer vos services backend node js et npm installés sur votre machine locale installez node js (version 14 x ou ultérieure) et npm à partir de nodejs org https //nodejs org/ vérifiez votre installation en exécutant node v et npm v dans votre terminal compréhension de base de react familiarité avec les composants react, les hooks et jsx si vous avez besoin de vous rafraîchir la mémoire sur react, consultez le documentation officielle de react https //reactjs org/docs/getting started html éditeur de code tout éditeur de code moderne comme visual studio code, sublime text ou atom git (optionnel) pour le contrôle de version et le suivi du dépôt ressources supplémentaires documentation de back4app https //www back4app com/docs/get started/welcome guide javascript de parse https //docs parseplatform org/js/guide/ documentation de chakra ui https //chakra ui com/docs/getting started documentation de react router https //reactrouter com/en/main étape 1 — configuration de votre backend back4app dans cette étape, vous allez créer un nouveau projet back4app et configurer le schéma de base de données nécessaire pour votre application de réseau social back4app fournit un serveur parse géré qui s'occupera de l'authentification des utilisateurs, du stockage des données et des fonctionnalités en temps réel créer un nouveau projet back4app connectez vous à votre compte back4app et accédez au tableau de bord cliquez sur le bouton "créer une nouvelle application" entrez "back4gram" comme nom de votre application, sélectionnez la région de serveur la plus proche, puis cliquez sur "créer" une fois votre application créée, vous serez redirigé vers le tableau de bord de l'application comprendre le schéma de la base de données avant de créer des classes dans votre base de données, comprenons le modèle de données nécessaire pour notre réseau social en fonction des exigences de notre application, nous aurons besoin des classes suivantes utilisateur (existe déjà par défaut dans parse) cette classe gère l'authentification des utilisateurs et les informations de profil nous l'étendrons avec des champs supplémentaires comme la biographie et l'avatar publication stocke les publications des utilisateurs, y compris le contenu textuel et les images champs contenu (chaîne), auteur (pointeur vers utilisateur), image (fichier), likes (nombre), commentaires (tableau), créé le (date) comment stocke les commentaires sur les publications champs contenu (chaîne), auteur (pointeur vers utilisateur), publication (pointeur vers publication), créé le (date) conversation représente une conversation de chat entre utilisateurs champs participants (tableau de pointeurs vers l'utilisateur), derniermessage (chaîne), mis à jour le (date) message messages individuels dans une conversation champs texte (chaîne), expéditeur (pointeur vers utilisateur), conversation (pointeur vers conversation), créé le (date) statut de saisie (pour les indicateurs de saisie en temps réel) suit les utilisateurs lorsqu'ils tapent dans une conversation champs utilisateur (pointeur vers utilisateur), conversation (pointeur vers conversation), estentaper (booléen) création de classes de base de données maintenant, créons ces classes dans votre base de données back4app accédez à la section "base de données" dans votre tableau de bord back4app étendre la classe utilisateur cliquez sur la classe "utilisateur" qui existe déjà ajoutez les colonnes suivantes bio (type chaîne) avatar (type fichier) abonnés (type nombre, par défaut 0) suivant (type nombre, par défaut 0) création de la classe post cliquez sur "créer une classe" entrez "post" comme nom de classe et sélectionnez "créer une classe vide" ajoutez les colonnes suivantes contenu (type chaîne) auteur (type pointeur vers utilisateur) image (type fichier) aime (type nombre, par défaut 0) commentaires (type tableau) créé à (type date, ajouté automatiquement) création de la classe comment cliquez sur "créer une classe" entrez "comment" comme nom de classe et sélectionnez "créer une classe vide" ajoutez les colonnes suivantes contenu (type chaîne) auteur (type pointeur vers utilisateur) publication (type pointeur vers la publication) créé à (type date, ajouté automatiquement) créer la classe conversation cliquez sur "créer une classe" entrez "conversation" comme nom de classe et sélectionnez "créer une classe vide" ajoutez les colonnes suivantes participants (type tableau) derniermessage (type chaîne) mis à jour le (type date, ajouté automatiquement) création de la classe message cliquez sur "créer une classe" entrez "message" comme nom de classe et sélectionnez "créer une classe vide" ajoutez les colonnes suivantes texte (type chaîne) expéditeur (type pointeur vers utilisateur) conversation (type pointeur vers la conversation) créé à (type date, ajouté automatiquement) création de la classe typingstatus cliquez sur "créer une classe" entrez "typingstatus" comme nom de classe et sélectionnez "créer une classe vide" ajoutez les colonnes suivantes utilisateur (type pointeur vers utilisateur) conversation (type pointeur vers la conversation) estentraindetaper (type booléen) configuration des autorisations de classe (facultatif) pour garantir la sécurité des données, nous devons configurer des listes de contrôle d'accès (acl) appropriées pour chaque classe accédez à la section "sécurité et clés" dans votre tableau de bord back4app sous "sécurité au niveau de la classe", configurez les permissions suivantes classe utilisateur accès public en lecture activé (pour que les utilisateurs puissent voir les profils des autres utilisateurs) accès en écriture public désactivé (les utilisateurs ne peuvent modifier que leurs propres profils) poste de classe accès public en lecture activé (tout le monde peut voir les publications) accès en écriture public activé (les utilisateurs authentifiés peuvent créer des publications) ajouter un clp pour la mise à jour/suppression afin de restreindre à l'auteur uniquement comment classe accès public en lecture activé (tout le monde peut voir les commentaires) accès en écriture public activé (les utilisateurs authentifiés peuvent créer des commentaires) ajouter un clp pour la mise à jour/suppression afin de restreindre à l'auteur uniquement classe de conversation accès public en lecture désactivé (les conversations sont privées) accès en écriture public activé (les utilisateurs authentifiés peuvent créer des conversations) ajouter un clp pour restreindre l'accès en lecture/écriture aux participants de la conversation classe de message accès public en lecture désactivé (les messages sont privés) accès en écriture public activé (les utilisateurs authentifiés peuvent envoyer des messages) ajouter un clp pour restreindre l'accès en lecture/écriture aux participants de la conversation classe typingstatus accès public en lecture désactivé (le statut de saisie est privé) accès en écriture public activé (les utilisateurs authentifiés peuvent mettre à jour le statut de saisie) ajouter un clp pour restreindre l'accès en lecture/écriture aux participants de la conversation configuration de livequery pour des fonctionnalités en temps réel pour activer des fonctionnalités en temps réel comme la messagerie et les indicateurs de saisie, nous devons configurer livequery accédez à la section "paramètres du serveur" dans votre tableau de bord back4app sous "parse server", trouvez la section "livequery" et activez la ajoutez les classes suivantes à surveiller par livequery message statut de saisie publication (pour des mises à jour en temps réel des likes et des commentaires) enregistrez vos modifications obtenir vos clés d'application vous aurez besoin de vos clés d'application back4app pour connecter votre frontend react au backend accédez à la section "paramètres de l'application" > "sécurité et clés" notez les clés suivantes id d'application clé javascript url du serveur url du serveur livequery (configuration de sous domaine, pour les fonctionnalités en temps réel) vous utiliserez ces clés dans votre application react pour initialiser parse étape 2 — création d'un projet frontend react dans cette étape, vous allez configurer un nouveau projet react et le configurer pour fonctionner avec votre backend back4app vous installerez les dépendances nécessaires, créerez la structure du projet et vous connecterez à votre serveur parse configuration d'un nouveau projet react commençons par créer une nouvelle application react en utilisant create react app, qui fournit une configuration de build moderne sans configuration ouvrez votre terminal et naviguez vers le répertoire où vous souhaitez créer votre projet exécutez la commande suivante pour créer une nouvelle application react npx create react app back4gram une fois le projet créé, naviguez vers le répertoire du projet cd back4gram démarrez le serveur de développement pour vous assurer que tout fonctionne npm start cela ouvrira votre nouvelle application react dans votre navigateur à http //localhost 3000 http //localhost 3000 installation des dépendances nécessaires maintenant, installons les paquets dont nous aurons besoin pour notre application de réseau social arrêtez le serveur de développement (appuyez sur ctrl+c dans votre terminal) installez le sdk parse pour vous connecter à back4app npm install parse installez react router pour la navigation npm install react router dom installez chakra ui pour nos composants d'interface utilisateur npm install @chakra ui/react @emotion/react @emotion/styled framer motion installez des utilitaires ui supplémentaires et des bibliothèques d'icônes npm install react icons explication de la structure du projet organisons notre projet avec une structure claire créez les répertoires suivants dans le src dossier mkdir p src/components/ui src/pages src/contexts src/utils voici à quoi sert chaque répertoire composants composants ui réutilisables ui composants ui de base comme des boutons, des formulaires, des modales autres dossiers de composants pour des fonctionnalités spécifiques (par exemple, publications, commentaires) pages composants de page complète qui correspondent aux routes contexts fournisseurs de contexte react pour la gestion d'état utils fonctions utilitaires et aides création de variables d'environnement pour stocker en toute sécurité vos identifiants back4app, créez un env fichier à la racine de votre projet créez un nouveau fichier nommé env local à la racine du projet touch env local ouvrez le fichier et ajoutez vos identifiants back4app 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 remplacez les valeurs de remplacement par vos véritables identifiants back4app de l'étape 1 assurez vous d'ajouter env local à votre gitignore fichier pour éviter de commettre des informations sensibles configurer le sdk parse avec les identifiants back4app maintenant, configurons le sdk parse pour se connecter à votre backend back4app créez un nouveau fichier src/utils/parseconfig js // src/utils/parseconfig js import parse from 'parse/dist/parse min js'; // initialiser 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; // initialiser les requêtes en direct if (process env react app parse live query url) { parse livequeryserverurl = process env react app parse live query url; } export default parse; mettez à jour votre src/index js fichier pour importer la configuration parse import react from 'react'; import reactdom from 'react dom/client'; import ' /index css'; import app from ' /app'; import reportwebvitals from ' /reportwebvitals'; import ' /utils/parseconfig'; // importer la configuration parse const root = reactdom createroot(document getelementbyid('root')); root render( \<react strictmode> \<app /> \</react strictmode> ); reportwebvitals(); configuration du composant app avec le routage mettons à jour le composant principal app pour inclure le routage et le fournisseur chakra ui mettre à jour src/app js import react from 'react'; import { browserrouter as router, routes, route } from 'react router dom'; import { chakraprovider, extendtheme } from '@chakra ui/react'; // importer les pages (nous allons les créer ensuite) 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'; // créer un thème personnalisé 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; créer un composant de route protégée pour sécuriser les routes qui nécessitent une authentification, créons un composant protectedroute tout d'abord, créez un authcontext pour gérer l'état d'authentification de l'utilisateur // 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>; } maintenant, créez le composant protectedroute // 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; mettez à jour le composant app pour utiliser authprovider et protectedroute // 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; créer une page d'atterrissage basique créons une simple page d'atterrissage pour tester notre configuration // 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; tester votre configuration maintenant que vous avez configuré la structure de base de votre application react et que vous l'avez connectée à back4app, testons la démarrez le serveur de développement npm start ouvrez votre navigateur et accédez à http //localhost 3000 http //localhost 3000 vous devriez voir la page d'accueil avec des boutons pour vous inscrire ou vous connecter vérifiez la console de votre navigateur pour vous assurer qu'il n'y a pas d'erreurs liées à l'initialisation de parse étape 3 — mise en œuvre des fonctionnalités d'authentification dans cette étape, nous allons mettre en œuvre des fonctionnalités d'authentification des utilisateurs pour notre application de réseau social en utilisant le serveur parse de back4app nous examinerons comment fonctionne le système d'authentification parse et mettrons en œuvre les fonctionnalités de connexion, d'inscription et de réinitialisation de mot de passe comprendre le système d'authentification des utilisateurs de parse le serveur parse de back4app fournit un système de gestion des utilisateurs complet grâce à la parse user classe comprenons comment fonctionne l'authentification parse dans notre application la classe parse user le parse user est une sous classe spéciale de parse object conçue spécifiquement pour la gestion des utilisateurs dans notre application back4gram, nous l'utilisons pour stocker les informations d'identification de l'utilisateur (nom d'utilisateur, email, mot de passe) gérer l'état d'authentification gérer automatiquement les jetons de session en regardant notre implémentation, nous pouvons voir comment nous interagissons avec la classe parse user // from signuppage js const user = new parse user(); user set('username', username); user set('email', email); user set('password', password); await user signup(); ce code crée un nouvel objet parse user, définit les champs requis et appelle la méthode signup() pour enregistrer l'utilisateur dans back4app flux d'authentification dans parse examinons comment l'authentification fonctionne dans notre application flux d'inscription dans notre signuppage js, nous collectons le nom d'utilisateur, l'email et le mot de passe nous validons les données d'entrée (vérification des champs vides, format d'email valide, longueur du mot de passe) nous créons un nouvel objet parse user et définissons les identifiants nous appelons signup() qui envoie les données à back4app analyse les hachages du mot de passe avant de le stocker en cas de succès, l'utilisateur est automatiquement connecté avec un jeton de session flux de connexion dans notre loginpage js, nous collectons le nom d'utilisateur et le mot de passe nous appelons parse user login() avec ces identifiants parse vérifie les identifiants par rapport aux données stockées si valide, parse génère un jeton de session le jeton de session est automatiquement stocké dans le stockage du navigateur gestion de session parse inclut automatiquement le jeton de session dans toutes les requêtes api nous utilisons parse user current() pour récupérer l'utilisateur actuellement connecté les sessions persistent à travers les actualisations de page mise en œuvre de l'inscription des utilisateurs examinons notre composant signuppage pour comprendre comment l'inscription des utilisateurs est mise en œuvre validation du formulaire avant d'envoyer des données à back4app, nous validons l'entrée de l'utilisateur // 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; }; cette validation garantit que le nom d'utilisateur n'est pas vide l'email est valide le mot de passe contient au moins 6 caractères le mot de passe et la confirmation correspondent gestion des erreurs d'inscription notre gestionnaire d'inscription inclut la gestion des erreurs spécifiques à parse // 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 renvoie des codes d'erreur spécifiques que nous pouvons utiliser pour fournir des retours utiles à l'utilisateur code 202 nom d'utilisateur déjà pris code 203 email déjà utilisé le code complet pour l'enregistrement de l'utilisateur/inscription peut être trouvé ici mise en œuvre de la connexion utilisateur notre composant loginpage gère l'authentification des utilisateurs en utilisant parse user login() formulaire de connexion le formulaire de connexion collecte le nom d'utilisateur et le mot de passe // 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> vérification de session comme mentionné précédemment, nous vérifions s'il existe une session lors du chargement de la page de connexion // 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]); c'est une fonctionnalité clé de parse elle gère automatiquement le jeton de session dans le stockage du navigateur, ce qui nous permet de vérifier facilement si un utilisateur est déjà connecté mise en œuvre de la réinitialisation du mot de passe back4app fournit un flux de réinitialisation de mot de passe intégré dans notre application, nous faisons un lien vers une page de réinitialisation de mot de passe depuis le formulaire de connexion // from loginpage js \<link as={routerlink} to="/reset password" alignself="flex end" fontsize="sm"> forgot password? \</link> le processus de réinitialisation du mot de passe dans back4app fonctionne comme suit l'utilisateur demande une réinitialisation de mot de passe avec son email parse envoie un lien de réinitialisation spécial à l'email de l'utilisateur l'utilisateur clique sur le lien et définit un nouveau mot de passe parse met à jour le hachage du mot de passe dans la base de données pour implémenter cela dans notre application, nous utiliserions // example password reset implementation try { await parse user requestpasswordreset(email); // show success message } catch (error) { // handle error } sécuriser les routes pour les utilisateurs authentifiés pour protéger certaines routes dans notre application, nous utilisons un composant protectedroute qui vérifie si un utilisateur est authentifié // 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; } ce composant utilise notre authcontext pour vérifier si un utilisateur est connecté affiche un indicateur de chargement pendant la vérification redirige vers la page de connexion si aucun utilisateur n'est trouvé rend le contenu protégé si un utilisateur est authentifié nous utilisons ce composant dans notre configuration de routage // from app js \<route path="/feed" element={ \<protectedroute> \<feedpage /> \</protectedroute> } /> configuration d'authentification back4app back4app propose plusieurs options de configuration pour l'authentification dans le tableau de bord vérification par e mail vous pouvez exiger une vérification par e mail avant que les utilisateurs ne puissent se connecter configurez cela dans "paramètres du serveur" > "serveur parse" > "authentification des utilisateurs" politique de mot de passe définir la longueur minimale du mot de passe et les exigences de complexité configurez cela dans "paramètres du serveur" > "serveur parse" > "authentification des utilisateurs" durée de session contrôlez combien de temps les sessions utilisateur restent valides configurez cela dans "paramètres du serveur" > "serveur parse" > "configuration de session" modèles d'e mail personnalisez les e mails de vérification et de réinitialisation de mot de passe configurez cela dans "paramètres de l'application" > "modèles d'e mail" tester votre mise en œuvre d'authentification pour s'assurer que votre système d'authentification fonctionne correctement tester l'enregistrement de l'utilisateur essayez de vous enregistrer avec des identifiants valides essayez de vous enregistrer avec un nom d'utilisateur existant (devrait afficher une erreur) vérifiez si l'utilisateur apparaît dans votre tableau de bord back4app sous la classe " user" tester la connexion de l'utilisateur essayez de vous connecter avec des identifiants corrects (devrait rediriger vers le fil) essayez de vous connecter avec des identifiants incorrects (devrait afficher une erreur) tester la persistance de session connectez vous et actualisez la page (devrait rester connecté) fermez et rouvrez le navigateur (devrait rester connecté si la session est valide) tester les routes protégées essayez d'accéder à /feed lorsque vous êtes déconnecté (devrait rediriger vers la connexion) essayez d'accéder à /feed lorsque vous êtes connecté (devrait afficher la page de fil) le code pour le composant de connexion se trouve ici étape 4 — développement de la fonctionnalité de fil d'actualité dans cette étape, vous allez mettre en œuvre la fonctionnalité principale des réseaux sociaux le fil d'actualité c'est ici que les utilisateurs créeront des publications, consulteront le contenu des autres et interagiront par le biais de likes et de commentaires nous utiliserons le parse server de back4app pour stocker et récupérer les publications, gérer les téléchargements de fichiers pour les images et mettre en œuvre des mises à jour en temps réel comprendre la structure de la page de flux la page de flux dans notre application a trois composants principaux une barre latérale pour la navigation la zone principale de flux avec création de post et liste de posts une section tendance (sur les écrans plus grands) examinons comment cela est implémenté dans notre feedpage js // 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> ); } cette mise en page réactive s'adapte à différentes tailles d'écran, cachant les barres latérales sur les appareils mobiles création de la classe post dans back4app avant de mettre en œuvre le frontend, assurons nous que notre base de données back4app est correctement configurée pour les publications la classe post devrait avoir les champs suivants contenu (string) le contenu textuel du post image (fichier) pièce jointe d'image facultative auteur (pointeur vers utilisateur) l'utilisateur qui a créé le post j'aime (nombre) compte des j'aime sur le post aimépar (tableau) tableau des identifiants d'utilisateur qui ont aimé le post crééà (date) ajouté automatiquement par parse définir les autorisations appropriées pour la classe post accès en lecture public tout le monde devrait pouvoir lire les posts accès en écriture public les utilisateurs authentifiés devraient pouvoir créer des posts autorisations de mise à jour/suppression seul l'auteur devrait pouvoir modifier ses posts mise en œuvre de la création de posts examinons comment la création de publications est implémentée dans notre composant feedpage // 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); } }; points clés sur la création de publications gestion des fichiers dans parse parse file est utilisé pour télécharger des images dans le stockage de back4app le fichier est d'abord enregistré, puis attaché à l'objet de publication back4app gère automatiquement le stockage des fichiers et génère des url création d'objets parse nous étendons la classe 'post' avec parse object extend('post') nous créons une nouvelle instance avec new post() nous définissons des propriétés en utilisant le set() méthode nous enregistrons l'objet dans back4app avec save() association d'utilisateur nous associons la publication à l'utilisateur actuel en utilisant parse user current() cela crée une relation de pointeur dans la base de données l'interface du formulaire de création de publication ressemble à ceci {/ 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> récupération et affichage des posts maintenant, voyons comment nous récupérons et affichons les publications de back4app // 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(); }, \[]); points clés sur la récupération des publications analyser les requêtes nous créons une requête avec new parse query(post) nous incluons des objets liés avec query include('author') nous trions avec query descending('createdat') nous paginons avec query limit() et query skip() nous exécutons la requête avec query find() traitement des résultats les objets parse ont une méthode get() pour accéder aux propriétés pour les champs de fichiers, nous utilisons file url() pour obtenir l'url nous transformons les objets parse en objets javascript simples pour l'état de react pagination nous mettons en œuvre la fonctionnalité "charger plus" avec le suivi des pages nous vérifions s'il y a plus de publications à charger avant de faire des demandes supplémentaires les publications sont affichées dans une liste {/ 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> )} implémentation de la fonctionnalité j'aime examinons comment la fonctionnalité de like est implémentée // 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', }); } }; points clés sur la fonctionnalité de like mises à jour optimistes nous mettons à jour l'interface utilisateur immédiatement avant que le serveur ne confirme le changement cela rend l'application plus réactive mises à jour des objets parse nous récupérons le post spécifique avec query get(postid) nous modifions ses propriétés avec post set() nous enregistrons les modifications avec post save() suivi des likes nous maintenons à la fois un compte ( likes ) et une liste d'utilisateurs ( likedby ) cela nous permet d'afficher des comptes précis et de déterminer si l'utilisateur actuel a aimé un post mise en œuvre des mises à jour en temps réel avec livequery (optionnel) pour que le fil d'actualités se mette à jour en temps réel lorsque de nouveaux posts sont créés, nous pouvons utiliser parse livequery // 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(); } }; }, \[]); points clés concernant livequery configuration de l'abonnement nous créons une requête et nous y abonnissons avec query subscribe() cela établit une connexion websocket au serveur livequery de back4app gestion des événements nous écoutons les événements 'create' lorsque de nouveaux posts sont créés nous écoutons les événements 'update' lorsque les posts sont modifiés nous mettons à jour notre état local en conséquence nettoyage nous nous désabonnissons lorsque le composant se démonte pour éviter les fuites de mémoire optimisation du chargement des posts avec pagination nous avons déjà mis en œuvre une pagination de base avec le bouton "charger plus" améliorons le avec le défilement infini // 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); } }; et ajoutez ceci à la fin de la liste des publications {/ infinite scroll trigger /} {hasmore && ( \<box id="load more trigger" h="20px" /> )} points clés sur le défilement infini intersection observer nous utilisons l'api intersection observer pour détecter quand l'utilisateur fait défiler jusqu'en bas lorsque l'élément déclencheur devient visible, nous chargeons plus de publications états de chargement nous suivons des états de chargement séparés pour le chargement initial et "charger plus" cela empêche plusieurs requêtes simultanées considérations de performance nous ne chargeons qu'un nombre fixe de publications à la fois (pagination) nous vérifions s'il y a plus de publications à charger avant de faire des requêtes supplémentaires optimisation des performances back4app pour optimiser les performances lors de l'utilisation de back4app utilisez des index ajoutez des index aux champs fréquemment interrogés dans votre tableau de bord back4app pour la classe post, ajoutez des index sur 'createdat' et 'author' requêtes sélectives utilisez query select() pour ne récupérer que les champs dont vous avez besoin cela réduit le transfert de données et améliore les performances optimisation des comptages au lieu de récupérer tous les posts pour les compter, utilisez query count() c'est plus efficace pour déterminer les totaux étape 6 — ajout d'interactions sociales dans cette étape, nous allons améliorer notre réseau social en mettant en œuvre des fonctionnalités clés d'interaction sociale commentaires sur les publications, profils d'utilisateur et paramètres d'utilisateur nous nous concentrerons sur la façon dont ces fonctionnalités interagissent avec le backend back4app et les mécanismes qui les font fonctionner mise en œuvre des commentaires sur les publications les commentaires sont une fonctionnalité fondamentale d'interaction sociale qui nécessite une modélisation des données appropriée dans back4app examinons comment notre application interagit avec le serveur parse pour mettre en œuvre des commentaires modèle de données back4app pour les commentaires dans back4app, les commentaires sont mis en œuvre comme une classe séparée avec des relations à la fois avec les utilisateurs et les publications structure de la classe commentaire contenu (string) le contenu textuel du commentaire auteur (pointeur vers l'utilisateur) pointe vers l'utilisateur qui a créé le commentaire publication (pointeur vers la publication) pointe vers la publication commentée créé le (date) géré automatiquement par parse types de relations utilisateur → commentaires un à plusieurs (un utilisateur peut créer plusieurs commentaires) publication → commentaires un à plusieurs (une publication peut avoir plusieurs commentaires) récupération des commentaires depuis back4app notre pagedétailspost utilise des requêtes parse pour récupérer les commentaires d'un post spécifique // 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', }); } }; mécanismes clés de back4app parse object extend() crée une référence à la classe comment dans back4app query equalto() crée une contrainte pour trouver uniquement les commentaires d'un post spécifique query include() effectue une opération de type jointure pour récupérer des objets liés dans une seule requête query descending() trie les résultats par un champ spécifique création de commentaires dans back4app lorsqu'un utilisateur ajoute un commentaire, nous créons un nouvel objet parse et établissons les relations // 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); } }; mécanismes clés de back4app new comment() crée une nouvelle instance de la classe comment comment set() définit les propriétés sur l'objet parse, y compris les pointeurs vers les objets liés comment save() envoie l'objet à back4app pour stockage parse user current() obtient l'utilisateur actuellement authentifié pour établir la relation d'auteur sécurité back4app pour les commentaires pour sécuriser correctement les commentaires dans back4app configurer les autorisations au niveau de la classe (clps) lire public (tout le monde peut lire les commentaires) écrire utilisateurs authentifiés uniquement (seuls les utilisateurs connectés peuvent commenter) mettre à jour/supprimer créateur uniquement (seul l'auteur du commentaire peut modifier ou supprimer) configurez ces autorisations dans votre tableau de bord back4app { "find" { " " true }, "get" { " " true }, "create" { " " true }, "update" { "requiresauthentication" true }, "delete" { "requiresauthentication" true }, "addfield" { "requiresauthentication" true } } étape 7 création de profils utilisateurs avec back4app les profils utilisateurs dans notre application tirent parti de la classe utilisateur intégrée de parse avec des champs personnalisés examinons comment profilepage js interagit avec back4app extensions de la classe utilisateur back4app la classe utilisateur de parse est étendue avec des champs supplémentaires pour notre réseau social champs utilisateur personnalisés avatar (fichier) photo de profil stockée dans le stockage de fichiers de back4app bio (chaîne) biographie de l'utilisateur site web (chaîne) url du site web de l'utilisateur nomaffiché (chaîne) nom affiché de l'utilisateur récupération des données utilisateur et des publications notre profilepage récupère à la fois les données utilisateur et les publications de l'utilisateur // 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); } }; mécanismes clés de back4app parse user current() récupère l'utilisateur authentifié à partir du jeton de session query equalto('author', currentuser) crée une contrainte d'égalité de pointeur pour trouver les publications de l'utilisateur actuel post get('image') url() accède à l'url d'un objet de fichier parse stocké dans back4app mise en œuvre des paramètres utilisateur la page des paramètres permet aux utilisateurs de mettre à jour leurs informations de profil et de gérer les paramètres de compte examinons comment elle interagit avec back4app // 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> ); } mécanismes clés de back4app parse user current() obtient l'utilisateur actuel pour mettre à jour ses paramètres currentuser set() met à jour les propriétés de l'utilisateur dans l'objet parse user currentuser save() persiste les modifications dans back4app schéma des paramètres utilisateur back4app pour mettre en œuvre les paramètres dans back4app ajoutez ces champs à la classe user paramètresdeconfidentialité (objet) objet json contenant les préférences de confidentialité paramètresdesécurité (objet) objet json contenant les paramètres de sécurité paramètresdenotification (objet) objet json contenant les préférences de notification exemple de schéma pour ces objets // paramètresdeconfidentialité { "visibilitéduprofil" "public", // ou "amis" ou "privé" "confidentialitédespublications" "amis", // ou "public" ou "privé" "afficheractivité" true } // paramètresdesécurité { "authentificationàdeuxfacteurs" false, "alertesdeconnexion" true } // paramètresdenotification { "j'aime" true, "commentaires" true, "abonnements" true, "messages" true } fonctions cloud back4app pour les interactions sociales pour des interactions sociales plus complexes, vous pouvez implémenter des fonctions cloud dans back4app par exemple, pour suivre les notifications de commentaires // 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 }); }); pour implémenter cela allez à votre tableau de bord back4app naviguez vers "cloud code" > "cloud functions" créez une nouvelle fonction avec le code ci dessus déployez la fonction étape 8 — construction de la messagerie en temps réel dans cette étape, nous allons implémenter une fonctionnalité de messagerie en temps réel en utilisant la fonctionnalité livequery de back4app cela permettra aux utilisateurs d'échanger des messages instantanément sans actualiser la page, créant une expérience de chat dynamique similaire aux plateformes de messagerie populaires comprendre back4app livequery avant de plonger dans l'implémentation, comprenons comment fonctionne livequery de back4app qu'est ce que livequery ? livequery est une fonctionnalité de parse server qui permet aux clients de s'abonner à des requêtes lorsque des objets correspondant à ces requêtes changent, le serveur envoie automatiquement des mises à jour aux clients abonnés cela crée une fonctionnalité en temps réel sans avoir à implémenter vous même une gestion complexe des websocket comment fonctionne livequery livequery établit une connexion websocket entre le client et le serveur les clients s'abonnent à des requêtes spécifiques qu'ils souhaitent surveiller lorsque les données correspondant à ces requêtes changent, le serveur envoie des événements via le websocket le client reçoit ces événements et met à jour l'interface utilisateur en conséquence événements livequery créer déclenché lorsqu'un nouvel objet correspondant à la requête est créé mise à jour déclenché lorsqu'un objet existant correspondant à la requête est mis à jour entrer déclenché lorsqu'un objet commence à correspondre à la requête laisser déclenché lorsque un objet ne correspond plus à la requête supprimer déclenché lorsqu'un objet correspondant à la requête est supprimé configuration de livequery dans back4app pour activer livequery pour votre application, suivez ces étapes activez votre sous domaine back4app connectez vous à votre compte back4app naviguez vers "paramètres de l'application" > "paramètres du serveur" trouvez le bloc "url du serveur et requête en direct" et cliquez sur "paramètres" vérifiez l'option "activer votre sous domaine back4app" ce sous domaine servira de serveur livequery activer livequery sur la même page de paramètres, cochez l'option "activer la requête en direct" sélectionnez les classes que vous souhaitez surveiller avec livequery message (pour les messages de chat) statut de saisie (pour les indicateurs de saisie) conversation (pour les mises à jour de conversation) enregistrez vos modifications notez l'url de votre serveur livequery l'url de votre serveur livequery sera au format wss\ //yourappname back4app io vous aurez besoin de cette url pour initialiser le client livequery dans votre application react configurer livequery dans votre application react pour utiliser livequery dans votre application react, vous devez initialiser un client livequery // 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' dans votre env local fichier, assurez vous d'inclure react app parse live query url=wss\ //yourappname back4app io création du modèle de données pour la messagerie notre système de messagerie nécessite deux classes principales dans back4app classe de conversation participants (tableau) tableau de pointeurs d'utilisateur pour les utilisateurs dans la conversation derniermessage (chaîne) le contenu du message le plus récent dernièredatemessage (date) horodatage du message le plus récent mis à jour le (date) géré automatiquement par parse classe de message conversation (pointeur) pointe vers la conversation à laquelle ce message appartient expéditeur (pointeur) pointe vers l'utilisateur qui a envoyé le message contenu (chaîne) le contenu textuel du message lire (booléen) indique si le message a été lu créé à (date) géré automatiquement par parse classe typingstatus conversation (pointeur) pointez vers la conversation utilisateur (pointeur) pointez vers l'utilisateur qui tape estentraindetaper (booléen) indique si l'utilisateur est actuellement en train de taper mise en œuvre de l'interface de messagerie examinons comment notre messagespage implémente la messagerie en temps réel // 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 } le composant maintient plusieurs états conversations liste des conversations de l'utilisateur selectedconversation la conversation actuellement sélectionnée messages messages dans la conversation sélectionnée typingusers utilisateurs actuellement en train de taper dans la conversation il utilise également des refs pour stocker les abonnements livequery et gérer les indicateurs de saisie s'abonner à livequery pour les messages la clé de la messagerie en temps réel est de s'abonner à livequery pour les messages dans la conversation actuelle // 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); } }; mécanismes clés de livequery créer une requête nous créons une requête pour les messages dans la conversation actuelle s'abonner à la requête nous appelons query subscribe() pour commencer à écouter les changements gestion des événements nous utilisons subscription on('create', callback) pour gérer les nouveaux messages se désabonner nous stockons la référence d'abonnement et nous nous désabonnons lorsque c'est nécessaire implémentation des indicateurs de saisie avec livequery les indicateurs de saisie sont une autre fonctionnalité en temps réel implémentée avec livequery // 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); } }; mise à jour du statut de saisie lorsqu'un utilisateur tape, nous mettons à jour son statut de saisie // 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); }; envoi de messages lors de l'envoi de messages, nous créons un nouvel objet message et laissons livequery gérer les mises à jour // 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, }); } }; nettoyage des abonnements livequery il est important de nettoyer les abonnements livequery lorsqu'ils ne sont plus nécessaires // 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); } }; }, \[]); considérations de performance de back4app livequery lors de la mise en œuvre de livequery, considérez ces conseils de performance soyez précis avec les requêtes abonnez vous uniquement aux données dont vous avez besoin utilisez des contraintes pour limiter la portée des abonnements par exemple, abonnez vous uniquement aux messages de la conversation actuelle gérez les abonnements avec soin désabonnez vous lorsque les données ne sont plus nécessaires créez de nouveaux abonnements lorsque le contexte change conservez des références d'abonnement pour vous désabonner plus tard utilisez des acl pour la sécurité définissez des acl appropriées sur les objets message et conversation assurez vous que les utilisateurs ne peuvent accéder qu'aux conversations auxquelles ils participent livequery respecte les acl, donc les utilisateurs non autorisés ne recevront pas de mises à jour optimisez le serveur livequery dans le tableau de bord back4app, configurez les classes qui ont besoin de livequery n'activez pas livequery pour les classes qui n'ont pas besoin de mises à jour en temps réel étape 9 — mise en œuvre de la fonctionnalité de recherche dans cette étape, nous allons mettre en œuvre une fonctionnalité de recherche complète pour notre réseau social les utilisateurs pourront rechercher d'autres utilisateurs, des publications par contenu et des hashtags cette fonctionnalité facilitera la découverte de contenu et la connexion avec d'autres sur la plateforme comprendre la recherche dans back4app avant de plonger dans l'implémentation, comprenons comment la recherche fonctionne dans back4app système de requête parse back4app utilise le système de requête de parse server pour la recherche les requêtes peuvent être effectuées sur plusieurs classes vous pouvez rechercher par correspondance exacte, contient, commence par, etc options de recherche de texte commencepar trouve des chaînes qui commencent par une chaîne spécifique contient trouve des chaînes qui contiennent une sous chaîne spécifique correspond utilise des expressions régulières pour un appariement de motifs plus complexe textecomplet (fonctionnalité entreprise) fournit des capacités avancées de recherche en texte intégral considérations de performance les recherches textuelles peuvent être gourmandes en ressources des index doivent être créés pour les champs fréquemment recherchés les requêtes doivent être optimisées pour limiter le nombre de résultats construire la page de recherche notre composant searchpage gérera différents types de recherches et affichera les résultats examinons sa structure // 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 } le composant maintient l'état pour la requête de recherche saisie par l'utilisateur le type de recherche effectuée les résultats de la recherche état de chargement sujets tendance mise en œuvre de la recherche d'utilisateurs voyons comment nous recherchons des utilisateurs dans back4app // 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); } }; mécanismes clés de back4app new parse query(parse user) crée une requête sur la classe user userquery matches('username', new regexp(query, 'i')) effectue une correspondance regex insensible à la casse sur les noms d'utilisateur userquery limit(20) limite les résultats pour améliorer les performances userquery find() exécute la requête et renvoie les utilisateurs correspondants mise en œuvre de la recherche de contenu de publication maintenant, voyons comment nous recherchons des publications par contenu // 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); } }; mécanismes clés de back4app parse object extend('post') fait référence à la classe post postquery matches('content', new regexp(query, 'i')) effectue une correspondance regex insensible à la casse sur le contenu des publications postquery include('author') inclut les informations de l'auteur dans une seule requête postquery descending('createdat') trie les résultats par date de création mise en œuvre de la recherche par hashtag la recherche par hashtag nécessite une approche différente nous allons rechercher des publications contenant des hashtags // 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); } }; mécanismes clés de back4app nous utilisons une regex avec des limites de mots ( \\\b ) pour trouver des hashtags réels cette approche trouve des publications où le contenu contient le hashtag spécifique mise en œuvre des sujets tendance pour mettre en œuvre des sujets tendance, nous devons analyser les publications récentes et compter les occurrences de hashtags // 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); } }; mécanismes clés de back4app nous interrogeons les publications des 7 derniers jours en utilisant query greaterthan('createdat', oneweekago) nous analysons le contenu pour extraire et compter les hashtags nous trions par fréquence pour trouver les hashtags les plus populaires gestion de l'exécution de la recherche voyons maintenant comment nous gérons l'exécution de la recherche en fonction du type de recherche // 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); } }; optimisation de la recherche dans back4app pour optimiser les performances de recherche dans back4app créer des index naviguez vers votre tableau de bord back4app allez à "navigateur de base de données" > sélectionnez la classe (par exemple, utilisateur, publication) cliquez sur l'onglet "index" créez des index pour les champs fréquemment recherchés pour la classe utilisateur créez un index sur nom d'utilisateur pour la classe publication créez un index sur contenu utilisez des contraintes de requête utilisez toujours limit() pour restreindre le nombre de résultats utilisez select() pour ne récupérer que les champs dont vous avez besoin utilisez skip() pour la pagination lors du traitement de grands ensembles de résultats considérez les fonctions cloud pour des recherches complexes pour une logique de recherche plus complexe, implémentez une fonction cloud cela vous permet d'effectuer un traitement côté serveur et de renvoyer des résultats optimisés exemple de fonction cloud pour une recherche avancée // 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; }); étape 10 — tester et déployer votre réseau social dans cette étape finale, nous allons aborder comment tester votre application, la préparer pour la production, la déployer sur un service d'hébergement, et surveiller et faire évoluer votre backend back4app ces étapes sont cruciales pour garantir que votre réseau social fonctionne sans problème dans un environnement de production tester votre application avant de déployer, il est important de tester soigneusement votre application pour détecter tout bug ou problème 1 test manuel créez un plan de test qui couvre toutes les fonctionnalités clés de votre application authentification de l'utilisateur test d'enregistrement avec des entrées valides et invalides tester la connexion avec des identifiants corrects et incorrects tester la fonctionnalité de réinitialisation du mot de passe tester la persistance de session et la déconnexion fonctionnalité de publication tester la création de publications avec du texte et des images tester l'affichage des publications dans le fil tester l'appréciation et les commentaires sur les publications tester la suppression de publications interactions sociales tester l'affichage des profils utilisateurs tester les commentaires sur les publications tester la messagerie en temps réel fonctionnalité de recherche tester la recherche d'utilisateurs tester la recherche de publications tester la recherche de hashtag test multi navigateur test sur chrome, firefox, safari et edge test sur les navigateurs mobiles 2 tests automatisés pour des tests plus robustes, mettez en œuvre des tests automatisés // 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 tests back4app testez votre configuration back4app fonctions cloud testez toutes les fonctions cloud avec diverses entrées sécurité vérifiez que vos autorisations au niveau de la classe fonctionnent correctement livequery testez la fonctionnalité en temps réel avec plusieurs clients préparation à la production avant de déployer, optimisez votre application pour la production 1 configuration de l'environnement créez des fichiers d'environnement séparés pour le développement et la production # 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 optimisation de la construction optimisez votre construction react // in your package json "scripts" { "analyze" "source map explorer 'build/static/js/ js'", "build" "generate sourcemap=false react scripts build" } installez le source map explorer pour analyser la taille de votre bundle npm install save dev source map explorer 3 optimisation des performances implémentez le découpage du code pour réduire le temps de chargement initial // 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> ); } déploiement sur un service d'hébergement il existe plusieurs options pour déployer votre application react 1 déploiement sur vercel vercel est une excellente option pour les applications react installez le cli vercel npm install g vercel déployez votre application vercel pour le déploiement en production vercel prod 2 déploiement sur netlify netlify est une autre excellente option installez le cli netlify npm install g netlify cli construisez votre application npm run build déployez sur netlify netlify deploy pour le déploiement en production netlify deploy prod 3 déploiement sur github pages pour une option de déploiement simple installer gh pages npm install save dev gh pages ajouter au package json "homepage" "https //yourusername github io/your repo name", "scripts" { "predeploy" "npm run build", "deploy" "gh pages d build" } déployer npm run deploy surveillance et mise à l'échelle de votre backend back4app à mesure que votre réseau social se développe, vous devrez surveiller et mettre à l'échelle votre backend back4app 1 surveiller la performance back4app fournit plusieurs outils pour surveiller votre application analyse du tableau de bord surveillez les requêtes api, l'utilisation de stockage et les opérations de fichiers journaux vérifiez les journaux du serveur pour les erreurs et les problèmes de performance métriques de performance suivez les temps de réponse et identifiez les goulets d'étranglement pour accéder à ces outils allez sur votre tableau de bord back4app naviguez vers "analyse" pour les statistiques d'utilisation vérifiez "journaux" pour des journaux d'opération détaillés 2 mise à l'échelle de votre backend lorsque votre base d'utilisateurs croît, vous devrez peut être mettre à l'échelle votre backend back4app mettez à niveau votre plan passez à un plan de niveau supérieur avec plus de ressources optimisez les requêtes utilisez des index et limitez les requêtes pour améliorer les performances implémentez la mise en cache utilisez la mise en cache côté client pour les données fréquemment consultées 3 optimisation de la base de données optimisez votre base de données pour de meilleures performances créer des index ajoutez des index aux champs fréquemment interrogés // exemple création d'un index sur le champ 'username' dans la classe user const schema = new parse schema(' user'); schema addindex('username index', { username 1 }); schema update(); utiliser le pipeline d'agrégation pour des opérations de données complexes // exemple compter les publications par utilisateur const pipeline = \[ { group { objectid '$author', count { $sum 1 } } } ]; const results = await parse cloud aggregate('post', pipeline); 4 mise en œuvre d'un cdn pour les médias pour une livraison plus rapide des images et des médias configurer un cdn comme cloudflare ou amazon cloudfront mettez à jour vos paramètres de stockage de fichiers back4app pour utiliser le cdn mettez à jour les url des fichiers dans votre application pour utiliser le domaine cdn 5 configuration des alertes de surveillance configurez des alertes pour être informé des problèmes allez sur votre tableau de bord back4app naviguez vers "paramètres de l'application" > "alertes" configurez des alertes pour utilisation élevée de l'api piques de taux d'erreur limites de taille de la base de données temps d'arrêt du serveur résumé de ce qui a été accompli tout au long de ce tutoriel, vous avez mettre en place une infrastructure backend robuste créé un compte back4app et configuré votre application conçu un schéma de base de données pour les utilisateurs, les publications, les commentaires et les messages paramètres de sécurité configurés et autorisations au niveau de la classe configurer livequery pour une fonctionnalité en temps réel construit un frontend moderne en react créé une interface utilisateur réactive avec des composants chakra ui mise en œuvre du routage côté client avec react router développé des composants réutilisables pour les publications, les commentaires et les profils d'utilisateur connecté votre frontend à back4app en utilisant le sdk javascript parse fonctionnalités de réseau social de base mises en œuvre authentification de l'utilisateur (inscription, connexion, réinitialisation du mot de passe) création de post et interaction (j'aime, commentaires) profils d'utilisateur et paramètres messagerie en temps réel entre les utilisateurs fonctionnalité de recherche pour les utilisateurs, les publications et les hashtags optimisé pour la production optimisations de performance mises en œuvre comme le découpage de code configurer les environnements pour le développement et la production appris à déployer votre application sur des services d'hébergement exploré des stratégies de surveillance et de mise à l'échelle pour votre backend back4app vous avez maintenant une base solide pour une application de réseau social qui peut être étendue et personnalisée pour répondre à vos besoins spécifiques prochaines étapes pour étendre l'application voici quelques façons passionnantes d'améliorer votre application de réseau social fonctionnalités multimédias avancées ajouter le support pour les téléchargements et la lecture de vidéos implémenter des filtres d'image et des outils d'édition créer des histoires ou des fonctionnalités de contenu éphémère ajouter le support des gif et d'autres médias riches interactions sociales améliorées implémentez un moteur de recommandation pour des suggestions d'amis ajouter des fonctionnalités de groupes ou de communautés créer des événements avec des capacités de rsvp développer un système de notification pour toutes les interactions des utilisateurs options de monétisation mettre en œuvre des fonctionnalités d'adhésion premium ajouter des achats in app pour des biens numériques créer un marché pour les transactions entre utilisateurs intégrer avec des processeurs de paiement comme stripe expérience mobile convertissez votre application en une application web progressive (pwa) développez des applications mobiles natives en utilisant react native implémenter des notifications push pour les appareils mobiles optimiser l'interface utilisateur pour différentes tailles d'écran et orientations analyse et perspectives intégrer des outils d'analyse pour suivre l'engagement des utilisateurs créer des tableaux de bord pour la performance du contenu mettre en œuvre des tests a/b pour les nouvelles fonctionnalités développer des insights sur le comportement des utilisateurs pour améliorer la plateforme modération de contenu mettre en œuvre un filtrage de contenu automatisé créer des systèmes de reporting pour le contenu inapproprié développer des outils d'administration pour la modération de contenu utilisez l'apprentissage automatique pour une analyse de contenu intelligente ressources supplémentaires pour l'apprentissage pour continuer à élargir vos connaissances et compétences, voici quelques ressources précieuses documentation et tutoriels back4app documentation de back4app https //www back4app com/docs/get started/welcome guide javascript de parse https //docs parseplatform org/js/guide/ chaîne youtube de back4app https //www youtube com/c/back4app react et javascript moderne documentation de react https //reactjs org/docs/getting started html javascript info https //javascript info/ cours de react sur egghead io https //egghead io/q/react conception ui et ux documentation de chakra ui https //chakra ui com/docs/getting started modèles de conception ui https //ui patterns com/ recherche ux du nielsen norman group https //www nngroup com/articles/ optimisation de la performance performance web dev https //web dev/performance scoring/ optimisation des performances de react https //reactjs org/docs/optimizing performance html google pagespeed insights https //developers google com/speed/pagespeed/insights/ communauté et soutien stack overflow https //stackoverflow\ com/questions/tagged/parse platform forum de la communauté parse https //community parseplatform org/ communauté des développeurs react https //dev to/t/react n'oubliez pas que construire un réseau social réussi est un processus itératif commencez par une base solide (que vous avez maintenant), recueillez les retours des utilisateurs et améliorez continuellement votre application en fonction des modèles d'utilisation réels nous espérons que ce tutoriel vous a fourni les connaissances et la confiance nécessaires pour créer des applications incroyables avec react et back4app bon codage