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.

A screenshot of a browser with buttons for selecting a user.

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í.

A screenshot of a browser showing information for four different container users.

Poznámka:

V tomto kurzu se předpokládá, že jste obeznámeni s přehledemfluid 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

  1. 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.

  2. 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
    
  3. Projekt se vytvoří v podsložce s názvem fluid-audience-tutorial. Přejděte k němu pomocí příkazu cd fluid-audience-tutorial.

  4. 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

  1. 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čky return . 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
        );
        }
    
  2. 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. Hodnota displayAudience určuje, jestli vykreslujeme komponentu AudienceDisplay nebo userIdSelection (viz TODO 2). Hodnota userId je identifikátor uživatele pro připojení ke kontejneru a containerId hodnota je kontejner, který se má načíst. Funkce handleSelectUser se handleContainerNotFound 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]);
    
  3. 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

  1. Vytvořte a otevřete soubor \src\AudienceDisplay.js v editoru kódu. Přidejte následující příkazy import:

        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 (vizTODO 1) zatímco SharedMapse použije ke konfiguraci containerSchema potřebného k vytvoření kontejneru (vizTODO 2).

  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.

  1. TODO 1 nahraďte následujícím kódem. Všimněte si, že hodnoty pro userIduserNamecontainerId budou předány z komponenty aplikace. Pokud neexistuje, containerIdvytvoří se nový kontejner. Všimněte si také, že containerId 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 na localhost:3000 ID kontejneru a ručně zadat. Při této implementaci chceme zabalit getContainer 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.

  1. 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ď user1user2 nebo random. Pokud je random ID, použijeme Math.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 v userNameList. 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ímco currentMember 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();
    
  2. 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 na fluidMembers hodnotu a currentMember. 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ím audience.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) };
        });
        }, []);
    
  3. TODO 4 nahraďte následujícím kódem. Všimněte si, že pokud nebyla fluidMembers inicializována nebo currentMember 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řipojení přechody 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, na membersChangedkterý zavoláme updateMembers . To funguje, protože cílová skupina služby generuje membersChanged událost při připojení kontejneru.

Vytvoření zobrazení

  1. 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áme member.userIdcurrentMember.userId , abychom zkontrolovali, jestli tento člen isSelf. 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 do list pole. Každá komponenta zobrazí členová data, například userIduserName a additionalDetails.

        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>
            );
        });
    
  2. TODO 6 nahraďte následujícím kódem. Tím se vykreslí všechny prvky členu, které jsme nasdíleli do list pole.

        return (
            <div>
                {list}
            </div>
        );
    

Nastavení komponenty UserIdSelection

  1. 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
        );
    }
    
  2. TODO 1 nahraďte následujícím kódem. Všimněte si, že onSelectUser funkce aktualizuje proměnné stavu v nadřazené komponentě aplikace a zobrazí výzvu ke změně zobrazení. Metoda handleSubmit je aktivována prvky tlačítka, které budou implementovány v TODO 2. handleChange Metoda se také používá k aktualizaci containerId stavové proměnné. Tato metoda bude volána ze vstupního elementu naslouchací proces událostí implementovaný v TODO 2. Všimněte si také, že aktualizujeme containerId hodnotu z elementu HTML pomocí ID containerIdInput (definovaného v TODO 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);
        };
    
  3. 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í do služby 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 poli userConfigrozšíř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.