Postupy: Používání funkcí cílové skupiny v rozhraní Fluid Framework
V tomto kurzu se dozvíte o použití cílové skupiny fluid frameworku s Reactem k vytvoření vizuální ukázky uživatelů, kteří se připojují k kontejneru. Objekt cílové skupiny obsahuje informace týkající se všech uživatelů připojených k kontejneru. V tomto příkladu se klientská knihovna Azure použije k vytvoření kontejneru a cílové skupiny.
Následující obrázek ukazuje tlačítka ID a vstupní pole ID kontejneru. Když pole ID kontejneru necháte prázdné a kliknete na tlačítko ID uživatele, vytvoří se nový kontejner a připojí se jako vybraný uživatel. Koncový uživatel může také zadat ID kontejneru a zvolit ID uživatele pro připojení existujícího kontejneru jako vybraného uživatele.
Následující obrázek ukazuje více uživatelů připojených ke kontejneru reprezentovaným poli. Pole s modrou osnovou představuje uživatele, který si klienta prohlíží, zatímco pole uvedená v černé barvě představují ostatní připojené uživatele. S tím, jak se k kontejneru připojí noví uživatelé s jedinečným ID, se zvýší počet polí.
Poznámka:
V tomto kurzu se předpokládá, že jste obeznámeni s přehledem fluid frameworku a že jste dokončili rychlý start. Měli byste také znát základy Reactu, vytváření projektů React a React Hooks.
Vytvoření projektu
Otevřete příkazový řádek a přejděte do nadřazené složky, do které chcete projekt vytvořit; např
C:\My Fluid Projects
.Na příkazovém řádku spusťte následující příkaz. (Všimněte si, že rozhraní příkazového řádku je npx, ne npm. Byla nainstalována při instalaci Node.js.)
npx create-react-app fluid-audience-tutorial
Projekt se vytvoří v podsložce s názvem
fluid-audience-tutorial
. Přejděte k němu pomocí příkazucd fluid-audience-tutorial
.Projekt používá následující knihovny fluid:
Knihovna Popis fluid-framework
Obsahuje distribuovanou datovou strukturu SharedMap, která synchronizuje data mezi klienty. @fluidframework/azure-client
Definuje připojení k serveru Fluid Service a definuje spouštěcí schéma kontejneru Fluid. @fluidframework/test-client-utils
Definuje InsecureTokenProvider potřebný k vytvoření připojení ke službě Fluid Service. Spuštěním následujícího příkazu nainstalujte knihovny.
npm install @fluidframework/azure-client @fluidframework/test-client-utils fluid-framework
Kódování projektu
Nastavení stavových proměnných a zobrazení komponent
Otevřete soubor
\src\App.js
v editoru kódu. Odstraňte všechny výchozíimport
příkazy. Pak z příkazu odstraňte všechny značkyreturn
. Pak přidejte příkazy importu pro komponenty a hooky React. Všimněte si, že v dalších krocích budeme implementovat importované komponenty AudienceDisplay a UserIdSelection . Soubor by měl vypadat takto: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 ); }
TODO 1
nahraďte následujícím kódem. Tento kód inicializuje proměnné místního stavu, které budou použity v rámci aplikace. HodnotadisplayAudience
určuje, jestli vykreslujeme komponentu AudienceDisplay nebo userIdSelection (vizTODO 2
). HodnotauserId
je identifikátor uživatele pro připojení ke kontejneru acontainerId
hodnota je kontejner, který se má načíst. FunkcehandleSelectUser
sehandleContainerNotFound
předávají jako zpětná volání do dvou zobrazení a spravují přechody stavu.handleSelectUser
se volá při pokusu o vytvoření nebo načtení kontejneru.handleContainerNotFound
je volána při vytváření nebo načítání kontejneru selže.Všimněte si, že hodnoty userId a containerId budou pocházet z komponenty UserIdSelection prostřednictvím
handleSelectUser
funkce.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]);
TODO 2
nahraďte následujícím kódem. Jak je uvedeno výše, proměnná určí,displayAudience
jestli vykreslujeme komponentu AudienceDisplay nebo komponentu UserIdSelection . Funkce pro aktualizaci stavových proměnných se také předávají do součástí jako vlastnosti.(displayAudience) ? <AudienceDisplay userId={userId} containerId={containerId} onContainerNotFound={handleContainerNotFound}/> : <UserIdSelection onSelectUser={handleSelectUser}/>
Nastavení komponenty AudienceDisplay
Vytvořte a otevřete soubor
\src\AudienceDisplay.js
v editoru kódu. Přidejte následující příkazyimport
:import { useEffect, useState } from "react"; import { SharedMap } from "fluid-framework"; import { AzureClient } from "@fluidframework/azure-client"; import { InsecureTokenProvider } from "@fluidframework/test-client-utils";
Všimněte si, že objekty importované z knihovny Fluid Framework jsou vyžadovány pro definování uživatelů a kontejnerů. V následujících krocích se AzureClient a InsecureTokenProvider použijí ke konfiguraci klientské služby (viz
TODO 1
) zatímco SharedMap se použije ke konfiguracicontainerSchema
potřebného k vytvoření kontejneru (vizTODO 2
).Přidejte následující funkční komponenty a pomocné funkce:
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 }
Všimněte si, že AudienceDisplay a AudienceList jsou funkční komponenty, které zpracovávají získávání a vykreslování dat cílové skupiny, zatímco
tryGetAudienceObject
metoda zpracovává vytváření kontejneru a služeb cílové skupiny.
Získání kontejneru a cílové skupiny
Pomocnou funkci můžete použít k získání dat tekutiny z objektu Audience do vrstvy zobrazení (stav React). Metoda tryGetAudienceObject
se volá, když se komponenta zobrazení načte po výběru ID uživatele. Vrácená hodnota je přiřazena k vlastnosti stavu React.
TODO 1
nahraďte následujícím kódem. Všimněte si, že hodnoty prouserId
userName
containerId
budou předány z komponenty aplikace. Pokud neexistuje,containerId
vytvoří se nový kontejner. Všimněte si také, žecontainerId
je uložen na hodnotě hash adresy URL. Uživatel, který zadává relaci z nového prohlížeče, může zkopírovat adresu URL z existujícího prohlížeče relací nebo přejít nalocalhost:3000
ID kontejneru a ručně zadat. Při této implementaci chceme zabalitgetContainer
volání do try catch v případě, že uživatel zadá ID kontejneru, který neexistuje. Další informace najdete v dokumentaci ke kontejnerům .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;
Získání cílové skupiny při připojování komponent
Teď, když jsme definovali, jak získat cílovou skupinu fluid, musíme Reactu sdělit, aby volal tryGetAudienceObject
, když je připojená komponenta Zobrazení cílové skupiny.
TODO 2
nahraďte následujícím kódem. Všimněte si, že ID uživatele bude pocházet z nadřazené komponenty jako buďuser1
user2
neborandom
. Pokud jerandom
ID, použijemeMath.random()
k vygenerování náhodného čísla jako ID. Kromě toho bude jméno namapováno na uživatele na základě jeho ID, jak je uvedeno vuserNameList
. Nakonec definujeme proměnné stavu, které budou ukládat připojené členy i aktuálního uživatele.fluidMembers
uloží seznam všech členů připojených k kontejneru, zatímcocurrentMember
bude obsahovat objekt člena představujícího aktuálního uživatele, který zobrazuje kontext prohlížeče.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();
TODO 3
nahraďte následujícím kódem. Tím se zavolátryGetAudienceObject
, kdy je komponenta připojena, a nastaví vrácené členy cílové skupiny nafluidMembers
hodnotu acurrentMember
. Všimněte si, že se vrátí objekt cílové skupiny v případě, že uživatel zadá id kontejneru, který neexistuje, a musíme je vrátit do zobrazení UserIdSelection (props.onContainerNotFound()
zpracuje přepnutí zobrazení). Je také vhodné zrušit registraci obslužných rutin událostí při odpojení komponenty React vrácenímaudience.off
.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) }; }); }, []);
TODO 4
nahraďte následujícím kódem. Všimněte si, že pokud nebylafluidMembers
inicializována nebocurrentMember
nebyla inicializována, zobrazí se prázdná obrazovka. Komponenta AudienceList vykreslí data členů pomocí stylů (která se mají implementovat v další části).if (!fluidMembers || !currentMember) return (<div/>); return ( <AudienceList fluidMembers={fluidMembers} currentMember={currentMember}/> )
Poznámka:
Přechody připojení můžou vést k krátkým časovým oknem, kde
getMyself
se vrátíundefined
. Důvodem je to, že aktuální připojení klienta se ještě nepřidá do cílové skupiny, takže se nenašlo odpovídající ID připojení. Abychom zabránili Reactu v vykreslení stránky bez členů cílové skupiny, přidáme naslouchací proces, namembersChanged
který zavolámeupdateMembers
. To funguje, protože cílová skupina služby generujemembersChanged
událost při připojení kontejneru.
Vytvoření zobrazení
TODO 5
nahraďte následujícím kódem. Všimněte si, že vykreslujeme součást seznamu pro každého člena předaného z komponenty AudienceDisplay . Pro každého člena nejprve porovnámemember.userId
currentMember.userId
, abychom zkontrolovali, jestli tento členisSelf
. Tímto způsobem můžeme odlišit uživatele klienta od ostatních uživatelů a zobrazit komponentu jinou barvou. Komponentu seznamu pak nasdílíme dolist
pole. Každá komponenta zobrazí členová data, napříkladuserId
userName
aadditionalDetails
.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> ); });
TODO 6
nahraďte následujícím kódem. Tím se vykreslí všechny prvky členu, které jsme nasdíleli dolist
pole.return ( <div> {list} </div> );
Nastavení komponenty UserIdSelection
Vytvořte a otevřete soubor
\src\UserIdSelection.js
v editoru kódu. Tato komponenta bude obsahovat tlačítka ID uživatele a vstupní pole ID kontejneru, která koncovým uživatelům umožňují zvolit své ID uživatele a relaci pro spolupráci. Přidejte následujícíimport
příkazy a funkční komponenty:import { useState } from 'react'; export const UserIdSelection = (props) => { // TODO 1: Define styles and handle user inputs return ( // TODO 2: Return view components ); }
TODO 1
nahraďte následujícím kódem. Všimněte si, žeonSelectUser
funkce aktualizuje proměnné stavu v nadřazené komponentě aplikace a zobrazí výzvu ke změně zobrazení. MetodahandleSubmit
je aktivována prvky tlačítka, které budou implementovány vTODO 2
.handleChange
Metoda se také používá k aktualizacicontainerId
stavové proměnné. Tato metoda bude volána ze vstupního elementu naslouchací proces událostí implementovaný vTODO 2
. Všimněte si také, že aktualizujemecontainerId
hodnotu z elementu HTML pomocí IDcontainerIdInput
(definovaného vTODO 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); };
TODO 2
nahraďte následujícím kódem. Tím se vykreslí tlačítka ID uživatele a vstupní pole ID kontejneru.<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>
Spusťte server Fluid a spusťte aplikaci.
Poznámka:
Aby se shodovaly se zbývajícími postupy, používá npx
tato část a npm
příkazy ke spuštění serveru Fluid. Kód v tomto článku ale může běžet i na serveru Azure Fluid Relay. Další informace najdete v tématu Postupy: Zřízení služby Azure Fluid Relay a postupy: Připojení ke službě Azure Fluid Relay
Spuštěním následujícího příkazu v příkazovém řádku spusťte službu Fluid Service.
npx @fluidframework/azure-local-service@latest
Otevřete nový příkazový řádek a přejděte do kořenového adresáře projektu; například C:/My Fluid Projects/fluid-audience-tutorial
. Spusťte aplikační server pomocí následujícího příkazu. Aplikace se otevře v prohlížeči. Tento proces může trvat několik minut.
npm run start
localhost:3000
Přejděte na kartu prohlížeče a zobrazte spuštěnou aplikaci. Pokud chcete vytvořit nový kontejner, vyberte tlačítko ID uživatele a nechte vstupní ID kontejneru prázdné. Pokud chcete simulovat nového uživatele, který se připojuje k relaci kontejneru, otevřete novou kartu prohlížeče a přejděte na localhost:3000
. Tentokrát zadejte hodnotu ID kontejneru, kterou najdete na adrese URL http://localhost:3000/#
první karty prohlížeče .
Poznámka:
Možná budete muset nainstalovat další závislost, aby byla tato ukázka kompatibilní s Webpackem 5. Pokud se zobrazí chyba kompilace související s balíčkem "buffer" nebo "url", spusťte npm install -D buffer url
a zkuste to znovu. To se vyřeší v budoucí verzi fluid frameworku.
Další kroky
- Zkuste v poli v
additionalDetails
poliuserConfig
rozšířit ukázku o více dvojic klíč/hodnota. - Zvažte integraci cílové skupiny do aplikace pro spolupráci, která využívá distribuované datové struktury, jako je SharedMap nebo SharedString.
- Přečtěte si další informace o cílové skupině.
Tip
Když v kódu provedete změny, projekt se automaticky znovu sestaví a aplikační server se znovu načte. Pokud ale provedete změny schématu kontejneru, projeví se pouze při zavření a restartování aplikačního serveru. Uděláte to tak, že se fokus přesunete na příkazový řádek a dvakrát stisknete kombinaci kláves Ctrl+C. Pak spusťte npm run start
znovu.