Anvisningar: Använda målgruppsfunktioner i Fluid Framework
I den här självstudien får du lära dig mer om hur du använder Fluid Framework-målgruppen med React för att skapa en visuell demonstration av användare som ansluter till en container. Målgruppsobjektet innehåller information om alla användare som är anslutna till containern. I det här exemplet används Azure-klientbiblioteket för att skapa containern och målgruppen.
Följande bild visar ID-knappar och ett indatafält för container-ID. Om du lämnar fältet för container-ID tomt och klickar på en användar-ID-knapp skapas en ny container och kopplas som vald användare. Alternativt kan slutanvändaren ange ett container-ID och välja ett användar-ID för att ansluta till en befintlig container som vald användare.
Nästa bild visar flera användare som är anslutna till en container som representeras av rutor. Rutan som beskrivs i blått representerar den användare som visar klienten medan rutorna som beskrivs i svart representerar de andra anslutna användarna. När nya användare ansluter till containern med unika ID:n ökar antalet rutor.
Kommentar
Den här självstudien förutsätter att du är bekant med Översikt över Fluid Framework och att du har slutfört snabbstarten. Du bör också känna till grunderna i React, skapa React-projekt och React Hooks.
Skapa projektet
Öppna en kommandotolk och gå till den överordnade mappen där du vill skapa projektet. t.ex.
C:\My Fluid Projects
.Kör följande kommando i kommandotolken. (Observera att CLI är npx, inte npm. Det installerades när du installerade Node.js.)
npx create-react-app fluid-audience-tutorial
Projektet skapas i en undermapp med namnet
fluid-audience-tutorial
. Navigera till den med kommandotcd fluid-audience-tutorial
.Projektet använder följande Fluid-bibliotek:
Bibliotek beskrivning fluid-framework
Innehåller den delade map-distribuerade datastrukturen som synkroniserar data mellan klienter. @fluidframework/azure-client
Definierar anslutningen till en fluidtjänstserver och definierar startschemat för fluidcontainern. @fluidframework/test-client-utils
Definierar den InsecureTokenProvider som behövs för att skapa anslutningen till en fluidtjänst. Kör följande kommando för att installera biblioteken.
npm install @fluidframework/azure-client @fluidframework/test-client-utils fluid-framework
Koda projektet
Konfigurera tillståndsvariabler och komponentvy
Öppna filen
\src\App.js
i kodredigeraren. Ta bort alla standardinstruktionerimport
. Ta sedan bort alla markeringar från -instruktionenreturn
. Lägg sedan till importinstruktioner för komponenter och React-krokar. Observera att vi kommer att implementera de importerade komponenterna AudienceDisplay och UserIdSelection i de senare stegen. Filen bör se ut så här:import { useState, useCallback } from "react"; import { AudienceDisplay } from "./AudienceDisplay"; import { UserIdSelection } from "./UserIdSelection"; export const App = () => { // TODO 1: Define state variables to handle view changes and user input return ( // TODO 2: Return view components ); }
Ersätt
TODO 1
med följande kod. Den här koden initierar lokala tillståndsvariabler som ska användas i programmet. VärdetdisplayAudience
avgör om vi återger AudienceDisplay-komponenten eller UserIdSelection-komponenten (seTODO 2
). VärdetuserId
är den användaridentifierare som ska anslutas till containern med ochcontainerId
värdet är containern som ska läsas in. FunktionernahandleSelectUser
ochhandleContainerNotFound
skickas som återanrop till de två vyerna och hanterar tillståndsövergångar.handleSelectUser
anropas när du försöker skapa/läsa in en container.handleContainerNotFound
anropas när det inte går att skapa/läsa in en container.Observera att värdena userId och containerId kommer från en UserIdSelection-komponent via
handleSelectUser
funktionen.const [displayAudience, setDisplayAudience] = useState(false); const [userId, setUserId] = useState(); const [containerId, setContainerId] = useState(); const handleSelectUser = useCallback((userId, containerId) => { setDisplayAudience(true) setUserId(userId); setContainerId(containerId); }, [displayAudience, userId, containerId]); const handleContainerNotFound = useCallback(() => { setDisplayAudience(false) }, [setDisplayAudience]);
Ersätt
TODO 2
med följande kod. Som anges ovan avgör variabelndisplayAudience
om vi återger AudienceDisplay-komponenten eller UserIdSelection-komponenten . Funktioner för att uppdatera tillståndsvariablerna skickas också till komponenter som egenskaper.(displayAudience) ? <AudienceDisplay userId={userId} containerId={containerId} onContainerNotFound={handleContainerNotFound}/> : <UserIdSelection onSelectUser={handleSelectUser}/>
Konfigurera AudienceDisplay-komponent
Skapa och öppna en fil
\src\AudienceDisplay.js
i kodredigeraren. Lägg till följandeimport
-uttryck:import { useEffect, useState } from "react"; import { SharedMap } from "fluid-framework"; import { AzureClient } from "@fluidframework/azure-client"; import { InsecureTokenProvider } from "@fluidframework/test-client-utils";
Observera att de objekt som importeras från Fluid Framework-biblioteket krävs för att definiera användare och containrar. I följande steg används AzureClient och InsecureTokenProvider för att konfigurera klienttjänsten (se
TODO 1
) medan SharedMap används för att konfigurera encontainerSchema
nödvändig för att skapa en container (seTODO 2
).Lägg till följande funktionella komponenter och hjälpfunktioner:
const tryGetAudienceObject = async (userId, userName, containerId) => { // TODO 1: Create container and return audience object } export const AudienceDisplay = (props) => { //TODO 2: Configure user ID, user name, and state variables //TODO 3: Set state variables and set event listener on component mount //TODO 4: Return list view } const AudienceList = (data) => { //TODO 5: Append view elements to list array for each member //TODO 6: Return list of member elements }
Observera att AudienceDisplay och AudienceList är funktionella komponenter som hanterar att hämta och återge målgruppsdata medan
tryGetAudienceObject
metoden hanterar skapandet av container- och målgruppstjänster.
Hämta container och målgrupp
Du kan använda en hjälpfunktion för att hämta fluiddata från objektet Målgrupp till visningslagret (react-tillståndet). Metoden tryGetAudienceObject
anropas när vykomponenten läses in när ett användar-ID har valts. Det returnerade värdet tilldelas till en react-tillståndsegenskap.
Ersätt
TODO 1
med följande kod. Observera att värdena föruserId
userName
containerId
skickas in från appkomponenten. Om det inte finns någoncontainerId
skapas en ny container. Observera också attcontainerId
lagras på URL-hashen. En användare som anger en session från en ny webbläsare kan kopiera URL:en från en befintlig sessionswebbläsare eller navigera tilllocalhost:3000
och manuellt mata in container-ID:t. Med den här implementeringen vill vi omsluta anropetgetContainer
i en försöksfångst om användaren anger ett container-ID som inte finns. Mer information finns i dokumentationen för containrar .const userConfig = { id: userId, name: userName, additionalDetails: { email: userName.replace(/\s/g, "") + "@example.com", date: new Date().toLocaleDateString("en-US"), }, }; const serviceConfig = { connection: { type: "local", tokenProvider: new InsecureTokenProvider("", userConfig), endpoint: "http://localhost:7070", }, }; const client = new AzureClient(serviceConfig); const containerSchema = { initialObjects: { myMap: SharedMap }, }; let container; let services; if (!containerId) { ({ container, services } = await client.createContainer(containerSchema)); const id = await container.attach(); location.hash = id; } else { try { ({ container, services } = await client.getContainer(containerId, containerSchema)); } catch (e) { return; } } return services.audience;
Hämta målgruppen på komponentmonteringen
Nu när vi har definierat hur du hämtar Fluid-målgruppen måste vi be React att anropa tryGetAudienceObject
när målgruppsvisningskomponenten är monterad.
Ersätt
TODO 2
med följande kod. Observera att användar-ID:t kommer från den överordnade komponenten som antingenuser1
user2
ellerrandom
. Om ID:t användsrandom
Math.random()
för att generera ett slumptal som ID. Dessutom mappas ett namn till användaren baserat på deras ID enligt beskrivningen iuserNameList
. Slutligen definierar vi de tillståndsvariabler som lagrar de anslutna medlemmarna och den aktuella användaren.fluidMembers
lagrar en lista över alla medlemmar som är anslutna till containern medancurrentMember
innehåller medlemsobjektet som representerar den aktuella användaren som visar webbläsarkontexten.const userId = props.userId == "random" ? Math.random() : props.userId; const userNameList = { "user1" : "User One", "user2" : "User Two", "random" : "Random User" }; const userName = userNameList[props.userId]; const [fluidMembers, setFluidMembers] = useState(); const [currentMember, setCurrentMember] = useState();
Ersätt
TODO 3
med följande kod. Detta anropartryGetAudienceObject
när komponenten monteras och anger de returnerade målgruppsmedlemmarna tillfluidMembers
ochcurrentMember
. Observera att vi kontrollerar om ett målgruppsobjekt returneras om en användare anger ett containerId som inte finns och vi måste returnera dem till userIdSelection-vyn (props.onContainerNotFound()
hanterar växling av vyn). Det är också bra att avregistrera händelsehanterare när React-komponenten demonteras genom attaudience.off
returnera .useEffect(() => { tryGetAudienceObject(userId, userName, props.containerId).then(audience => { if(!audience) { props.onContainerNotFound(); alert("error: container id not found."); return; } const updateMembers = () => { setFluidMembers(audience.getMembers()); setCurrentMember(audience.getMyself()); } updateMembers(); audience.on("membersChanged", updateMembers); return () => { audience.off("membersChanged", updateMembers) }; }); }, []);
Ersätt
TODO 4
med följande kod. Observera att omfluidMembers
ellercurrentMember
inte har initierats återges en tom skärm. AudienceList-komponenten renderar medlemsdata med formatering (som ska implementeras i nästa avsnitt).if (!fluidMembers || !currentMember) return (<div/>); return ( <AudienceList fluidMembers={fluidMembers} currentMember={currentMember}/> )
Kommentar
Anslutningsövergångar kan resultera i korta tidsfönster där
getMyself
returnerarundefined
. Det beror på att den aktuella klientanslutningen inte har lagts till i målgruppen ännu, så det går inte att hitta ett matchande anslutnings-ID. För att förhindra att React återger en sida utan målgruppsmedlemmar lägger vi till en lyssnare för att anropaupdateMembers
påmembersChanged
. Detta fungerar eftersom tjänstpubliken genererar enmembersChanged
händelse när containern är ansluten.
Skapa vyn
Ersätt
TODO 5
med följande kod. Observera att vi återger en listkomponent för varje medlem som skickas från AudienceDisplay-komponenten . För varje medlem jämför vi först medmember.userId
currentMember.userId
att kontrollera om medlemmenisSelf
. På så sätt kan vi skilja klientanvändaren från andra användare och visa komponenten med en annan färg. Sedan push-överför vi listkomponenten till enlist
matris. Varje komponent visar medlemsdata somuserId
userName
ochadditionalDetails
.const currentMember = data.currentMember; const fluidMembers = data.fluidMembers; const list = []; fluidMembers.forEach((member, key) => { const isSelf = (member.userId === currentMember.userId); const outlineColor = isSelf ? 'blue' : 'black'; list.push( <div style={{ padding: '1rem', margin: '1rem', display: 'flex', outline: 'solid', flexDirection: 'column', maxWidth: '25%', outlineColor }} key={key}> <div style={{fontWeight: 'bold'}}>Name</div> <div> {member.userName} </div> <div style={{fontWeight: 'bold'}}>ID</div> <div> {member.userId} </div> <div style={{fontWeight: 'bold'}}>Connections</div> { member.connections.map((data, key) => { return (<div key={key}>{data.id}</div>); }) } <div style={{fontWeight: 'bold'}}>Additional Details</div> { JSON.stringify(member.additionalDetails, null, '\t') } </div> ); });
Ersätt
TODO 6
med följande kod. Detta renderar alla medlemselement som vi push-överförde till matrisenlist
.return ( <div> {list} </div> );
Konfigurera UserIdSelection-komponent
Skapa och öppna en fil
\src\UserIdSelection.js
i kodredigeraren. Den här komponenten innehåller användar-ID-knappar och indatafält för container-ID som gör det möjligt för slutanvändare att välja användar-ID och samarbetssession. Lägg till följandeimport
instruktioner och funktionella komponenter:import { useState } from 'react'; export const UserIdSelection = (props) => { // TODO 1: Define styles and handle user inputs return ( // TODO 2: Return view components ); }
Ersätt
TODO 1
med följande kod. Observera attonSelectUser
funktionen uppdaterar tillståndsvariablerna i den överordnade appkomponenten och uppmanar till en vyändring. MetodenhandleSubmit
utlöses av knappelement som ska implementeras iTODO 2
.handleChange
Dessutom används metoden för att uppdatera tillståndsvariabelncontainerId
. Den här metoden anropas från en händelselyssnare för indataelement som implementeras iTODO 2
. Observera också att vi uppdaterarcontainerId
att hämta värdet från ett HTML-element med ID:tcontainerIdInput
(definierat iTODO 2
).const selectionStyle = { marginTop: '2rem', marginRight: '2rem', width: '150px', height: '30px', }; const [containerId, setContainerId] = (location.hash.substring(1)); const handleSubmit = (userId) => { props.onSelectUser(userId, containerId); } const handleChange = () => { setContainerId(document.getElementById("containerIdInput").value); };
Ersätt
TODO 2
med följande kod. Detta renderar användar-ID-knapparna samt indatafältet för container-ID.<div style={{display: 'flex', flexDirection:'column'}}> <div style={{marginBottom: '2rem'}}> Enter Container Id: <input type="text" id="containerIdInput" value={containerId} onChange={() => handleChange()} style={{marginLeft: '2rem'}}></input> </div> { (containerId) ? (<div style={{}}>Select a User to join container ID: {containerId} as the user</div>) : (<div style={{}}>Select a User to create a new container and join as the selected user</div>) } <nav> <button type="submit" style={selectionStyle} onClick={() => handleSubmit("user1")}>User 1</button> <button type="submit" style={selectionStyle} onClick={() => handleSubmit("user2")}>User 2</button> <button type="submit" style={selectionStyle} onClick={() => handleSubmit("random")}>Random User</button> </nav> </div>
Starta fluidservern och kör programmet
Kommentar
För att matcha resten av den här instruktioner använder npx
det här avsnittet och npm
kommandon för att starta en Fluid-server. Koden i den här artikeln kan dock också köras mot en Azure Fluid Relay-server. Mer information finns i Så här etablerar du en Azure Fluid Relay-tjänst och Så här ansluter du till en Azure Fluid Relay-tjänst
I kommandotolken kör du följande kommando för att starta fluidtjänsten.
npx @fluidframework/azure-local-service@latest
Öppna en ny kommandotolk och navigera till projektets rot. till exempel C:/My Fluid Projects/fluid-audience-tutorial
. Starta programservern med följande kommando. Programmet öppnas i webbläsaren. Detta kan ta några minuter.
npm run start
Gå till localhost:3000
på en webbläsarflik för att visa det program som körs. Om du vill skapa en ny container väljer du en användar-ID-knapp medan du lämnar container-ID:t tomt. Om du vill simulera att en ny användare ansluter till containersessionen öppnar du en ny webbläsarflik och navigerar till localhost:3000
. Den här gången anger du container-ID-värdet som kan hittas från den första webbläsarflikens URL som fortsätter http://localhost:3000/#
.
Kommentar
Du kan behöva installera ytterligare ett beroende för att göra den här demonstrationen kompatibel med webpack 5. Om du får ett kompileringsfel relaterat till ett "buffert" eller "url"-paket kör npm install -D buffer url
du och försöker igen. Detta kommer att lösas i en framtida version av Fluid Framework.
Nästa steg
- Prova att utöka demonstrationen med fler nyckel/värde-par i fältet
additionalDetails
iuserConfig
. - Överväg att integrera målgruppen i ett samarbetsprogram som använder distribuerade datastrukturer som SharedMap eller SharedString.
- Läs mer om Målgrupp.
Dricks
När du gör ändringar i koden återskapas projektet automatiskt och programservern läses in igen. Men om du gör ändringar i containerschemat börjar de bara gälla om du stänger och startar om programservern. Det gör du genom att fokusera på kommandotolken och trycka på Ctrl-C två gånger. Kör npm run start
sedan igen.