Cara: Menggunakan fitur audiens di Fluid Framework
Dalam tutorial ini, Anda akan mempelajari tentang menggunakan Audiens Fluid Framework dengan React untuk membuat demonstrasi visual pengguna yang terhubung ke kontainer. Objek audiens menyimpan informasi yang terkait dengan semua pengguna yang terhubung ke kontainer. Dalam contoh ini, pustaka Klien Azure akan digunakan untuk membuat kontainer dan audiens.
Gambar berikut menunjukkan tombol ID dan bidang input ID kontainer. Membiarkan bidang ID kontainer kosong dan mengklik tombol ID pengguna akan membuat kontainer baru dan bergabung sebagai pengguna yang dipilih. Atau, pengguna akhir dapat memasukkan ID kontainer dan memilih ID pengguna untuk bergabung dengan kontainer yang ada sebagai pengguna yang dipilih.
Gambar berikutnya memperlihatkan beberapa pengguna yang tersambung ke kontainer yang diwakili oleh kotak. Kotak yang diuraikan dengan warna biru mewakili pengguna yang melihat klien sementara kotak yang diuraikan dalam warna hitam mewakili pengguna lain yang terhubung. Saat pengguna baru melampirkan ke kontainer dengan ID unik, jumlah kotak akan meningkat.
Catatan
Tutorial ini mengasumsikan bahwa Anda terbiasa dengan Gambaran Umum Kerangka Kerja Fluid dan bahwa Anda telah menyelesaikan Mulai Cepat. Anda juga harus terbiasa dengan dasar-dasar React, membuat proyek React, dan React Hooks.
Membuat proyek
Buka Prompt Perintah dan navigasi ke folder induk tempat Anda ingin membuat proyek; misalnya,
C:\My Fluid Projects
.Jalankan perintah berikut pada prompt. (Perhatikan bahwa CLI adalah npx, bukan npm. Ini diinstal ketika Anda menginstal Node.js.)
npx create-react-app fluid-audience-tutorial
Proyek dibuat dalam subfolder bernama
fluid-audience-tutorial
. Navigasikan ke dalamnya dengan perintahcd fluid-audience-tutorial
.Proyek ini menggunakan pustaka Fluid berikut:
Pustaka Deskripsi fluid-framework
Berisi struktur data terdistribusi SharedMap yang menyinkronkan data di seluruh klien. @fluidframework/azure-client
Menentukan koneksi ke server layanan Fluid dan menentukan skema awal untuk kontainer Fluid. @fluidframework/test-client-utils
Menentukan InsecureTokenProvider yang diperlukan untuk membuat koneksi ke Fluid Service. Jalankan perintah berikut untuk menginstal pustaka.
npm install @fluidframework/azure-client @fluidframework/test-client-utils fluid-framework
Kode proyek
Menyiapkan variabel status dan tampilan komponen
Buka file
\src\App.js
di editor kode. Hapus semua pernyataan defaultimport
. Kemudian hapus semua markup darireturn
pernyataan. Kemudian tambahkan pernyataan impor untuk komponen dan kait React. Perhatikan bahwa kami akan menerapkan komponen AudienceDisplay dan UserIdSelection yang diimpor di langkah selanjutnya. File akan terlihat seperti berikut: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 ); }
Ganti
TODO 1
dengan kode berikut. Kode ini menginisialisasi variabel status lokal yang akan digunakan dalam aplikasi. NilaidisplayAudience
menentukan apakah kita merender komponen AudienceDisplay atau komponen UserIdSelection (lihatTODO 2
). NilainyauserId
adalah pengidentifikasi pengguna untuk terhubung ke kontainer dengan dancontainerId
nilainya adalah kontainer yang akan dimuat. FungsihandleSelectUser
danhandleContainerNotFound
diteruskan sebagai panggilan balik ke dua tampilan dan mengelola transisi status.handleSelectUser
dipanggil saat mencoba membuat/memuat kontainer.handleContainerNotFound
dipanggil saat membuat/memuat kontainer gagal.Perhatikan, nilai userId dan containerId akan berasal dari komponen UserIdSelection melalui
handleSelectUser
fungsi .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]);
Ganti
TODO 2
dengan kode berikut. Seperti yang dinyatakandisplayAudience
di atas, variabel akan menentukan apakah kita merender komponen AudienceDisplay atau komponen UserIdSelection . Selain itu, fungsi untuk memperbarui variabel status diteruskan ke komponen sebagai properti.(displayAudience) ? <AudienceDisplay userId={userId} containerId={containerId} onContainerNotFound={handleContainerNotFound}/> : <UserIdSelection onSelectUser={handleSelectUser}/>
Menyiapkan komponen AudienceDisplay
Buat dan buka file
\src\AudienceDisplay.js
di editor kode. Tambahkan pernyataanimport
berikut:import { useEffect, useState } from "react"; import { SharedMap } from "fluid-framework"; import { AzureClient } from "@fluidframework/azure-client"; import { InsecureTokenProvider } from "@fluidframework/test-client-utils";
Perhatikan bahwa objek yang diimpor dari pustaka Fluid Framework diperlukan untuk menentukan pengguna dan kontainer. Dalam langkah-langkah berikut, AzureClient dan InsecureTokenProvider akan digunakan untuk mengonfigurasi layanan klien (lihat
TODO 1
) sementara SharedMap akan digunakan untuk mengonfigurasicontainerSchema
yang diperlukan untuk membuat kontainer (lihatTODO 2
).Tambahkan komponen fungsi dan fungsi pembantu berikut:
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 }
Perhatikan bahwa AudienceDisplay dan AudienceList adalah komponen fungsi yang menangani mendapatkan dan merender data audiens saat
tryGetAudienceObject
metode menangani pembuatan kontainer dan layanan audiens.
Mendapatkan kontainer dan audiens
Anda dapat menggunakan fungsi pembantu untuk mendapatkan data Fluid, dari objek Audiens, ke lapisan tampilan (status React). Metode tryGetAudienceObject
ini dipanggil ketika komponen tampilan dimuat setelah ID pengguna dipilih. Nilai yang dikembalikan ditetapkan ke properti status React.
Ganti
TODO 1
dengan kode berikut. Perhatikan bahwa nilai untukuserId
userName
containerId
akan diteruskan dari komponen Aplikasi. Jika tidakcontainerId
ada , kontainer baru dibuat. Selain itu, perhatikan bahwacontainerId
disimpan di hash URL. Pengguna yang memasukkan sesi dari browser baru dapat menyalin URL dari browser sesi yang ada atau menavigasi kelocalhost:3000
dan memasukkan ID kontainer secara manual. Dengan implementasi ini, kami ingin membungkusgetContainer
panggilan dalam tangkapan percobaan dalam kasus bahwa pengguna memasukkan ID kontainer yang tidak ada. Kunjungi dokumentasi Kontainer untuk informasi selengkapnya.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;
Mendapatkan audiens pada pemasangan komponen
Sekarang setelah kita menentukan cara mendapatkan audiens Fluid, kita perlu memberi tahu React untuk memanggil tryGetAudienceObject
saat komponen Tampilan Audiens dipasang.
Ganti
TODO 2
dengan kode berikut. Perhatikan bahwa ID pengguna akan berasal dari komponen induk sebagaiuser1
user2
ataurandom
. Jika ID digunakanrandom
Math.random()
untuk menghasilkan angka acak sebagai ID. Selain itu, nama akan dipetakan ke pengguna berdasarkan ID mereka seperti yang ditentukan dalamuserNameList
. Terakhir, kami menentukan variabel status yang akan menyimpan anggota yang terhubung serta pengguna saat ini.fluidMembers
akan menyimpan daftar semua anggota yang terhubung ke kontainer sedangkancurrentMember
akan berisi objek anggota yang mewakili pengguna saat ini yang melihat konteks browser.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();
Ganti
TODO 3
dengan kode berikut. Ini akan memanggiltryGetAudienceObject
ketika komponen dipasang dan mengatur anggota audiens yang dikembalikan kefluidMembers
dancurrentMember
. Catatan, kita memeriksa apakah objek audiens dikembalikan jika pengguna memasukkan containerId yang tidak ada dan kita perlu mengembalikannya ke tampilan UserIdSelection (props.onContainerNotFound()
akan menangani peralihan tampilan). Juga, adalah praktik yang baik untuk membatalkan pendaftaran penanganan aktivitas ketika komponen React melepas dengan mengembalikanaudience.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) }; }); }, []);
Ganti
TODO 4
dengan kode berikut. Perhatikan, jikafluidMembers
ataucurrentMember
belum diinisialisasi, layar kosong akan dirender. Komponen AudienceList akan merender data anggota dengan gaya (akan diimplementasikan di bagian berikutnya).if (!fluidMembers || !currentMember) return (<div/>); return ( <AudienceList fluidMembers={fluidMembers} currentMember={currentMember}/> )
Catatan
Transisi koneksi dapat mengakibatkan jendela waktu pendek tempat
getMyself
mengembalikanundefined
. Ini karena koneksi klien saat ini belum akan ditambahkan ke audiens, sehingga ID koneksi yang cocok tidak dapat ditemukan. Untuk mencegah React merender halaman tanpa anggota audiens, kami menambahkan pendengar untuk memanggilupdateMembers
.membersChanged
Ini berfungsi karena audiens layanan memancarkanmembersChanged
peristiwa saat kontainer terhubung.
Membuat tampilan
Ganti
TODO 5
dengan kode berikut. Perhatikan bahwa kami merender komponen daftar untuk setiap anggota yang diteruskan dari komponen AudienceDisplay . Untuk setiap anggota, pertama-tama kami membandingkancurrentMember.userId
denganmember.userId
memeriksa apakah anggotaisSelf
tersebut . Dengan cara ini, kita dapat membedakan pengguna klien dari pengguna lain dan menampilkan komponen dengan warna yang berbeda. Kami kemudian mendorong komponen daftar kelist
array. Setiap komponen akan menampilkan data anggota sepertiuserId
userName
danadditionalDetails
.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> ); });
Ganti
TODO 6
dengan kode berikut. Ini akan merender semua elemen anggota yang kami dorong kelist
dalam array.return ( <div> {list} </div> );
Menyiapkan komponen UserIdSelection
Buat dan buka file
\src\UserIdSelection.js
di editor kode. Komponen ini akan menyertakan tombol ID pengguna dan bidang input ID kontainer yang memungkinkan pengguna akhir untuk memilih ID pengguna dan sesi kolaboratif mereka. Tambahkan pernyataan danimport
komponen fungsi berikut:import { useState } from 'react'; export const UserIdSelection = (props) => { // TODO 1: Define styles and handle user inputs return ( // TODO 2: Return view components ); }
Ganti
TODO 1
dengan kode berikut. Perhatikan bahwaonSelectUser
fungsi akan memperbarui variabel status di komponen Aplikasi induk dan meminta perubahan tampilan. MetodehandleSubmit
ini dipicu oleh elemen tombol yang akan diimplementasikan diTODO 2
. Selain ituhandleChange
, metode ini digunakan untuk memperbaruicontainerId
variabel status. Metode ini akan dipanggil dari pendengar peristiwa elemen input yang diimplementasikan diTODO 2
. Perhatikan juga bahwa kami memperbaruicontainerId
mendapatkan nilai dari elemen HTML dengan idcontainerIdInput
(didefinisikan dalamTODO 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); };
Ganti
TODO 2
dengan kode berikut. Ini akan merender tombol ID pengguna serta bidang input ID kontainer.<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>
Mulai server Fluid dan jalankan aplikasi
Catatan
Untuk mencocokkan cara penggunaan lainnya, bagian ini menggunakan npx
dan npm
perintah untuk memulai server Fluid. Namun, kode dalam artikel ini juga dapat berjalan terhadap server Azure Fluid Relay. Untuk informasi selengkapnya, lihat Cara: Menyediakan layanan Azure Fluid Relay dan Cara: Menyambungkan ke layanan Azure Fluid Relay
Di Prompt Perintah, jalankan perintah berikut untuk memulai layanan Fluid.
npx @fluidframework/azure-local-service@latest
Buka Prompt Perintah baru dan navigasi ke akar proyek; misalnya, C:/My Fluid Projects/fluid-audience-tutorial
. Mulai server aplikasi dengan perintah berikut. Aplikasi terbuka di browser. Proses ini memerlukan waktu beberapa menit.
npm run start
Navigasikan ke localhost:3000
pada tab browser untuk melihat aplikasi yang sedang berjalan. Untuk membuat kontainer baru, pilih tombol ID pengguna sambil membiarkan input ID kontainer kosong. Untuk mensimulasikan pengguna baru yang bergabung dengan sesi kontainer, buka tab browser baru dan navigasi ke localhost:3000
. Kali ini, masukkan nilai ID kontainer yang dapat ditemukan dari url tab browser pertama yang melanjutkan http://localhost:3000/#
.
Catatan
Anda mungkin perlu menginstal dependensi tambahan untuk membuat demo ini kompatibel dengan Webpack 5. Jika Anda menerima kesalahan kompilasi yang terkait dengan paket "buffer" atau "url", silakan jalankan npm install -D buffer url
dan coba lagi. Ini akan diselesaikan dalam rilis Fluid Framework di masa mendatang.
Langkah berikutnya
- Coba perluas demo dengan lebih banyak pasangan kunci/nilai di
additionalDetails
bidang diuserConfig
. - Pertimbangkan untuk mengintegrasikan audiens ke dalam aplikasi kolaboratif yang menggunakan struktur data terdistribusi seperti SharedMap atau SharedString.
- Pelajari selengkapnya tentang Audiens.
Tip
Ketika Anda membuat perubahan pada kode, proyek akan secara otomatis dibangun ulang dan server aplikasi akan memuat ulang. Namun, jika Anda membuat perubahan pada skema kontainer, perubahan tersebut hanya akan berlaku jika Anda menutup dan menghidupkan ulang server aplikasi. Untuk melakukan ini, berikan fokus ke Prompt Perintah dan tekan Ctrl-C dua kali. Kemudian jalankan npm run start
lagi.