Verwenden von Zielgruppenfeatures im Fluid-Framework
In diesem Tutorial erfahren Sie, wie Sie eine Zielgruppe in Fluid Framework mit React verwenden, um eine visuelle Demonstration von Benutzer*innen, die eine Verbindung mit einem Container herstellen, zu erstellen. Das Zielgruppenobjekt enthält Informationen zu allen Benutzer*innen, die mit dem Container verbunden sind. In diesem Beispiel wird die Azure-Clientbibliothek zum Erstellen des Containers und der Zielgruppe verwendet.
Die folgende Abbildung zeigt ID-Schaltflächen und ein Container-ID-Eingabefeld. Wenn Sie das Feld für die Container-ID leer lassen und auf eine Benutzer*innen-ID-Schaltfläche klicken, wird ein neuer Container erstellt und als ausgewählte*r Benutzer*in eingebunden. Alternativ können die Endbenutzer*innen eine Container-ID eingeben und eine Benutzer-ID auswählen, um einen vorhandenen Container als ausgewählte*r Benutzer*in zu verknüpfen.
Die nächste Abbildung zeigt mehrere durch Felder dargestellte Benutzer*innen, die mit einem Container verbunden sind. Das blau umrissene Feld stellt den oder die Benutzer*in dar, der bzw. die den Client anzeigt, während die schwarz umrissenen Felder die anderen verbundenen Benutzer*innen darstellen. Wenn neue Benutzer*innen mit eindeutigen IDs an den Container angefügt werden, erhöht sich die Anzahl der Felder.
Hinweis
In diesem Tutorial wird davon ausgegangen, dass Sie mit der Übersicht über Fluid Framework vertraut sind und den Schnellstart abgeschlossen haben. Sie sollten auch mit den Grundlagen von React, dem Erstellen von React-Projekten und React-Hooks vertraut sein.
Erstellen eines Projekts
Öffnen Sie eine Eingabeaufforderung, und navigieren Sie zu dem übergeordneten Ordner, in dem Sie das Projekt erstellen möchten, z. B.
C:\My Fluid Projects
.Führen Sie an der Eingabeaufforderung den folgenden Befehl aus. (Beachten Sie, dass die Befehlszeilenschnittstelle npx und nicht npm heißt. Sie wurde beim Installieren von Node.js installiert.)
npx create-react-app fluid-audience-tutorial
Das Projekt wird in einem Unterordner mit dem Namen
fluid-audience-tutorial
erstellt. Navigieren Sie mit dem Befehlcd fluid-audience-tutorial
zu ihm.Das Projekt verwendet die folgenden Fluid-Bibliotheken:
Bibliothek Beschreibung fluid-framework
Es enthält die verteilte Datenstruktur SharedMap, die Daten clientübergreifend synchronisiert. @fluidframework/azure-client
Es definiert die Verbindung mit einem Fluid-Dienstserver und das Startschema für den Fluid-Container. @fluidframework/test-client-utils
Es definiert den erforderlichen InsecureTokenProvider zum Erstellen der Verbindung mit einem Fluid-Dienst. Führen Sie den folgenden Befehl aus, um die Bibliotheken zu installieren.
npm install @fluidframework/azure-client @fluidframework/test-client-utils fluid-framework
Programmieren des Projekts
Einrichten von Zustandsvariablen und der Komponentenansicht
Öffnen Sie im Code-Editor die Datei
\src\App.js
. Löschen Sie alleimport
-Standardanweisungen. Löschen Sie dann das gesamte Markup aus derreturn
-Anweisung. Fügen Sie anschließend Importanweisungen für Komponenten und React-Hooks hinzu. Beachten Sie, dass die importierten AudienceDisplay - und UserIdSelection-Komponenten in den späteren Schritten implementiert werden. Die Datei sollte folgendermaßen aussehen: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 ); }
Ersetzen Sie
TODO 1
durch den folgenden Code. Dieser Code initialisiert lokale Zustandsvariablen, die in der Anwendung verwendet werden. Der WertdisplayAudience
legt fest, ob die Komponente AudienceDisplay oder UserIdSelection gerendert wird (sieheTODO 2
). Der WertuserId
ist der Benutzerbezeichner für die Verbindung mit dem Container, und der WertcontainerId
ist der zu ladende Container. Die FunktionenhandleSelectUser
undhandleContainerNotFound
werden als Rückrufe an die beiden Ansichten übergeben und verwalten Zustandsübergänge.handleSelectUser
wird aufgerufen, wenn versucht wird, einen Container zu erstellen/zu laden.handleContainerNotFound
wird aufgerufen, wenn beim Erstellen/Laden eines Containers ein Fehler auftritt.Beachten Sie, dass die Werte „userId“ und „containerId“ von einer UserIdSelection-Komponente über die
handleSelectUser
-Funktion abgerufen werden.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]);
Ersetzen Sie
TODO 2
durch den folgenden Code. Wie oben erwähnt, legt die VariabledisplayAudience
fest, welche der Komponenten AudienceDisplay oder UserIdSelection gerendert wird. Außerdem werden Funktionen zum Aktualisieren der Zustandsvariablen als Eigenschaften an die Komponenten übergeben.(displayAudience) ? <AudienceDisplay userId={userId} containerId={containerId} onContainerNotFound={handleContainerNotFound}/> : <UserIdSelection onSelectUser={handleSelectUser}/>
Einrichten der Komponente AudienceDisplay
Erstellen Sie die Datei
\src\AudienceDisplay.js
, und öffnen Sie sie im Code-Editor. Fügen Sie die folgendenimport
-Anweisungen ein:import { useEffect, useState } from "react"; import { SharedMap } from "fluid-framework"; import { AzureClient } from "@fluidframework/azure-client"; import { InsecureTokenProvider } from "@fluidframework/test-client-utils";
Beachten Sie, dass die aus der Fluid Framework-Bibliothek importierten Objekte zum Definieren von Benutzer*innen und Containern erforderlich sind. In den folgenden Schritten werden AzureClient und InsecureTokenProvider zum Konfigurieren des Clientdiensts (siehe
TODO 1
) verwendet, während SharedMap verwendet wird, um ein zum Erstellen eines Containers erforderlichescontainerSchema
zu konfigurieren (sieheTODO 2
).Fügen Sie die folgenden funktionalen Komponenten und Hilfsfunktionen hinzu:
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 }
Beachten Sie, dass AudienceDisplay und AudienceList funktionale Komponenten sind, die das Abrufen und Rendern von Zielgruppendaten übernehmen, während die
tryGetAudienceObject
-Methode für die Erstellung von Containern und Zielgruppendiensten verantwortlich ist.
Abrufen von Containern und Zielgruppen
Sie können mit einer Hilfsfunktion die Fluid-Daten aus dem Zielgruppenobjekt in die Ansichtsebene (den React-Zustand) abrufen. Die tryGetAudienceObject
-Methode wird aufgerufen, wenn die Ansichtskomponente nach dem Auswählen einer Benutzer-ID geladen wird. Der zurückgegebene Wert wird einer React-Zustandseigenschaft zugewiesen.
Ersetzen Sie
TODO 1
durch den folgenden Code. Beachten Sie, dass die Werte füruserId
userName
containerId
die App-Komponente übergeben werden. Wenn keincontainerId
Container vorhanden ist, wird ein neuer Container erstellt. Beachten Sie außerdem, dass dercontainerId
im URL-Hash gespeichert ist. Ein Benutzer oder eine Benutzerin, der bzw. die über einen neuen Browser in eine Sitzung eintritt, kann die URL aus einem vorhandenen Sitzungsbrowser kopieren oder zulocalhost:3000
navigieren und die Container-ID manuell eingeben. Bei dieser Implementierung möchten wir dengetContainer
Aufruf in einen Try Catch einschließen, wenn der Benutzer eine Container-ID eingibt, die nicht vorhanden ist. Weitere Informationen finden Sie in der Containerdokumentation .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;
Abrufen der Zielgruppe beim Einbinden der Komponente
Nachdem nun definiert wurde, wie die Fluid-Zielgruppe abgerufen wird, muss React angewiesen werden, beim Einbinden der Komponente für die Zielgruppenanzeige tryGetAudienceObject
aufzurufen.
Ersetzen Sie
TODO 2
durch den folgenden Code. Beachten Sie, dass die Benutzer-ID von der übergeordneten Komponente als entwederuser1
user2
oderrandom
. Wenn die IDrandom
lautet, wird mitMath.random()
eine Zufallszahl als ID generiert. Darüber hinaus wird dem oder der Benutzer*in ein Name basierend auf der ID zugeordnet, wie inuserNameList
angegeben. Schließlich werden die Zustandsvariablen definiert, in denen die verbundenen Member und der oder die aktuelle Benutzer*in gespeichert werden. InfluidMembers
wird eine Liste aller Elemente gespeichert, die mit dem Container verbunden sind, währendcurrentMember
das Memberobjekt für den oder die aktuelle*n Benutzer*in bei der Anzeige des Browserkontexts darstellt.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();
Ersetzen Sie
TODO 3
durch den folgenden Code. Hiermit wirdtryGetAudienceObject
beim Einbinden der Komponente aufgerufen, und die zurückgegebenen Zielgruppenmitglieder werden auffluidMembers
undcurrentMember
festgelegt. Beachten Sie, dass überprüft wird, ob ein Benutzergruppenobjekt zurückgegeben wird, falls ein Benutzer eine containerId eingibt, die nicht vorhanden ist und wir sie zur UserIdSelection-Ansicht zurückgeben müssen (props.onContainerNotFound()
behandelt den Wechsel der Ansicht). Es empfiehlt sich außerdem, die Registrierung von Ereignishandlern durch Zurückgeben vonaudience.off
aufzuheben, wenn Bereitstellung der React-Komponente aufgehoben wird.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) }; }); }, []);
Ersetzen Sie
TODO 4
durch den folgenden Code. Beachten Sie, dass ein leerer Bildschirm gerendert wird, wennfluidMembers
odercurrentMember
nicht initialisiert wurde. Die Komponente AudienceList rendert die Memberdaten mit Formatierung (im nächsten Abschnitt implementiert).if (!fluidMembers || !currentMember) return (<div/>); return ( <AudienceList fluidMembers={fluidMembers} currentMember={currentMember}/> )
Hinweis
Verbindungsübergänge können zu kurzen Zeitfenstern führen, in denen
getMyself
undefined
zurückgibt. Dies liegt daran, dass die aktuelle Clientverbindung der Zielgruppe noch nicht hinzugefügt wurde, sodass keine übereinstimmende Verbindungs-ID gefunden werden kann. Um React daran zu hindern, eine Seite ohne Zielgruppenmitglieder zu rendern, wird ein Listener hinzugefügt, derupdateMembers
inmembersChanged
aufruft. Dies funktioniert, da die Dienstgruppe beim Verbinden des Containers einmembersChanged
-Ereignis ausgibt.
Erstellen der Ansicht
Ersetzen Sie
TODO 5
durch den folgenden Code. Beachten Sie, dass eine Listenkomponente für jeden Member gerendert wird, der von der Komponente AudienceDisplay übergeben wird. Für jeden Member wird zuerstmember.userId
mitcurrentMember.userId
verglichen, um zu überprüfen, ob esisSelf
für diesen Member zutrifft. Auf diese Weise kann der oder Clientbenutzer*in von den anderen Benutzer*innen unterschieden und die Komponente in einer anderen Farbe angezeigt werden. Anschließend wird die Listenkomponente in einlist
-Array gepusht. Jede Komponente zeigt Memberdaten an, zuserId
userName
. B. undadditionalDetails
.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> ); });
Ersetzen Sie
TODO 6
durch den folgenden Code. Dadurch werden alle Memberelemente gerendert, die in daslist
-Array gepusht wurden.return ( <div> {list} </div> );
Einrichten der Komponente UserIdSelection
Erstellen Sie die Datei
\src\UserIdSelection.js
, und öffnen Sie sie im Code-Editor. Diese Komponente enthält Benutzer-ID-Schaltflächen und Eingabefelder für die Container-ID, mit denen Endbenutzer*innen ihre Benutzer-ID und ihre Zusammenarbeitssitzung auswählen können. Fügen Sie die folgendenimport
-Anweisungen und Funktionskomponenten hinzu:import { useState } from 'react'; export const UserIdSelection = (props) => { // TODO 1: Define styles and handle user inputs return ( // TODO 2: Return view components ); }
Ersetzen Sie
TODO 1
durch den folgenden Code. Beachten Sie, dass dieonSelectUser
-Funktion die Zustandsvariablen in der übergeordneten App-Komponente aktualisiert und eine Ansichtsänderung hervorruft. DiehandleSubmit
-Methode wird durch Schaltflächenelemente ausgelöst, die inTODO 2
implementiert werden. Außerdem wird mit derhandleChange
-Methode die ZustandsvariablecontainerId
aktualisiert. Diese Methode wird von einem inTODO 2
implementierten Ereignislistener für Eingabeelemente aufgerufen. Beachten Sie außerdem, dasscontainerId
aktualisiert wird, sodass der Wert aus einem HTML-Element mit der IDcontainerIdInput
(definiert inTODO 2
) abgerufen wird.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); };
Ersetzen Sie
TODO 2
durch den folgenden Code. Dadurch werden die Schaltflächen für die Benutzer-ID sowie das Eingabefeld für die Container-ID gerendert.<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>
Starten des Fluid-Servers und Ausführen der Anwendung
Hinweis
In Übereinstimmung mit dem Rest dieser exemplarischen Vorgehensweise wird in diesem Abschnitt ein Fluid-Server mit den Befehlen npx
und npm
, gestartet. Der Code in diesem Artikel kann jedoch auch für einen Azure Fluid Relay-Server ausgeführt werden. Weitere Informationen finden Sie unter Bereitstellen eines Azure Fluid Relay-Diensts und Herstellen einer Verbindung mit einem Azure Fluid Relay-Dienst.
Führen Sie an der Eingabeaufforderung den folgenden Befehl aus, um den Fluid-Dienst zu starten.
npx @fluidframework/azure-local-service@latest
Öffnen Sie eine neue Eingabeaufforderung, und navigieren Sie zum Stammverzeichnis des Projekts, z. B. C:/My Fluid Projects/fluid-audience-tutorial
. Starten Sie den Anwendungsserver mit dem folgenden Befehl. Die Anwendung wird im Browser geöffnet. Dies kann einige Minuten dauern.
npm run start
Navigieren Sie auf einer Browserregisterkarte zu localhost:3000
, um die ausgeführte Anwendung anzuzeigen. Um einen neuen Container zu erstellen, wählen Sie eine Benutzer-ID-Schaltfläche aus, und lassen Sie die Container-ID-Eingabe leer. Um einen neuen Benutzer oder eine neue Benutzerin zu simulieren, der bzw. die der Containersitzung beitritt, öffnen Sie eine neue Browserregisterkarte, und navigieren Sie zu localhost:3000
. Geben Sie diesmal den Container-ID-Wert ein, den Sie der URL der ersten Browserregisterkarte nach http://localhost:3000/#
entnehmen können.
Hinweis
Möglicherweise müssen Sie eine zusätzliche Abhängigkeit installieren, um diese Demo mit Webpack 5 kompatibel zu machen. Wenn Sie einen Kompilierungsfehler im Zusammenhang mit einem Paket des Typs „buffer“ oder „url“ erhalten, führen Sie npm install -D buffer url
aus, und versuchen Sie es erneut. Dies wird in einem zukünftigen Release von Fluid Framework behoben.
Nächste Schritte
- Versuchen Sie, die Demo um weitere Schlüssel-Wert-Paare im Feld
additionalDetails
inuserConfig
zu erweitern. - Ziehen Sie in Betracht, die Zielgruppe in eine kollaborative Anwendung zu integrieren, die verteilte Datenstrukturen wie SharedMap oder SharedString verwendet.
- Erfahren Sie mehr über die Zielgruppe.
Tipp
Wenn Sie Änderungen am Code vornehmen, wird das Projekt automatisch neu erstellt, und der Anwendungsserver wird neu geladen. Wenn Sie jedoch Änderungen am Containerschema vornehmen, werden diese erst wirksam, nachdem Sie den Anwendungsserver schließen und neu starten. Setzen Sie dazu den Fokus auf die Eingabeaufforderung, und drücken Sie zweimal STRG-C. Führen Sie npm run start
dann erneut aus.