注: 以下の翻訳の正確性は検証されていません。AIPを利用して英語版の原文から機械的に翻訳されたものです。
useAdmin フックは、Foundry Admin API のユーザーデータを操作する機能を提供するカスタム React フックです。現在認証されているユーザーの取得、複数のユーザーの一括取得、プロフィール画像の管理など、ユーザー関連の操作を一元化します。
このフックは SWR (stale-while-revalidate) を活用して、効率的なデータ取得とキャッシュ戦略を実現します。これにより、ネットワークリクエストを最適化し、アプリケーション全体でユーザーデータに対する一貫したインターフェースを提供します。SWR と Foundry Admin SDK を組み合わせることで、読み込み状態、キャッシュ、エラー処理を自動的に管理する堅牢なユーザー管理ソリューションを実現します。
useCallback を使用して関数をメモ化し、不要な再レンダリングを防いでパフォーマンスを最適化しますuseAdmin の構造Copied!1 2 3interface UserDetails { [key: string]: User; }
このインターフェースは、文字列キー(ユーザーID)を User オブジェクトに対応付ける辞書型の構造を定義します。このパターンにより、次のことが可能になります。
useAdmin フックは、いくつかのデータ取得戦略を実装しています。
Copied!1 2 3 4const getCurrentUserDetails = useCallback(async () => { const user: User = await getCurrent(client); return { "currentUser": user }; }, [client]);
Copied!1 2 3 4 5 6const getCurrentProfilePictureUrl: (user: User) => Promise<string> = useCallback(async (user) => { const profilePictureResponse = await profilePicture(client, user.id); const blob = await profilePictureResponse.blob(); return URL.createObjectURL(blob); }, [client]);
getCurrentUserDetails:現在認証されているユーザーを取得します。getCurrentProfilePictureUrl:ユーザーのプロフィール画像の blob URL を取得します。getBatchUserDetails:キャッシュの最適化により、複数のユーザーを効率的に取得します。useAdmin フックは読み取り操作に重点を置いており、ユーザーデータの作成、更新、削除操作は実装していません。
useAdmin フックは、次の構造を持つオブジェクトを返します。
Copied!1 2 3 4 5 6 7 8 9{ users: UserDetails | undefined; // 取得したすべてのユーザーを含むオブジェクト currentUser: User | undefined; // 現在ログインしているユーザー isLoading: boolean; // データ取得時の読み込み状態 isValidating: boolean; // データを再検証中かどうか isError: Error | undefined; // エラーがある場合のエラー状態 getBatchUserDetails: (userIds: string[]) => Promise<UserDetails>; // 複数のユーザーを取得する関数 getCurrentProfilePictureUrl: (user: User) => Promise<string>; // ユーザーのプロフィール画像の URL を取得する関数 }
useAdmin フックは、ユーザーデータの取得にキャッシュ優先戦略を実装しています。
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27const getBatchUserDetails: (userIds: string[]) => Promise<UserDetails> = useCallback(async (userIds) => { const cachedUsers: UserDetails = {}; const usersToFetch: string[] = []; // 要求されたユーザーごとに、まずキャッシュを確認します userIds.forEach((userId) => { const cachedUser: State<unknown, unknown> | undefined = cache.get(`user-${userId}`); if (cachedUser && cachedUser.data) { cachedUsers[userId] = cachedUser.data as User; } else { usersToFetch.push(userId); } }); // キャッシュに見つからなかったユーザーのみを取得します if (usersToFetch.length > 0) { const usersRequest = await getBatch(client, usersToFetch.map((userId) => ({ userId }))); // 後で使用できるように結果をキャッシュに保存します Object.entries(usersRequest.data).forEach(([userId, user]) => { cachedUsers[userId] = user; mutate(`user-${userId}`, user, { revalidate: false }); }); } return cachedUsers; }, [cache, client]);
この戦略は、次の手順でパフォーマンスを向上させます。
useAdmin フックは、API レスポンスを blob URL に変換することで、バイナリーデータ(プロフィール画像)を処理するパターンを実装しています。
Copied!1 2 3 4 5 6const getCurrentProfilePictureUrl: (user: User) => Promise<string> = useCallback(async (user) => { const profilePictureResponse = await profilePicture(client, user.id); const blob = await profilePictureResponse.blob(); return URL.createObjectURL(blob); }, [client]);
このパターンは、次の処理を行います。
次の外部パッケージを useAdmin フックと併用できます。
目的: オントロジー SDK のクライアントインスタンスにアクセスするための React フック 利点:
目的: ユーザー関連のサービスを操作するための Foundry Admin SDK です。 利点:
User 型を使用して、ユーザーデータの型安全なインターフェースを提供しますgetCurrent、profilePicture、getBatch)を含みます目的: データ取得、キャッシュ、状態管理のためのライブラリー 利点:
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76import useAdmin from '../dataServices/useAdmin'; import { useState, useEffect } from 'react'; import type { User } from '@osdk/foundry.admin'; // 例1:現在のユーザー情報をプロフィール画像とともに表示する function UserProfile() { const { currentUser, isLoading, isError, getCurrentProfilePictureUrl } = useAdmin(); const [profilePicUrl, setProfilePicUrl] = useState<string | null>(null); useEffect(() => { async function loadProfilePic() { if (currentUser) { try { const url = await getCurrentProfilePictureUrl(currentUser); setProfilePicUrl(url); } catch (error) { console.error("Failed to load profile picture", error); } } } loadProfilePic(); }, [currentUser, getCurrentProfilePictureUrl]); if (isLoading) return <div>Loading user information...</div>; if (isError) return <div>Error loading user information</div>; if (!currentUser) return <div>No user found</div>; return ( <div className="user-profile"> {profilePicUrl && <img src={profilePicUrl} alt="Profile" className="profile-pic" />} <h1>{currentUser.username}</h1> <p>Email: {currentUser.email ?? "Not set"}</p> <p>User ID: {currentUser.id}</p> </div> ); } // 例2:共同作業者の一覧を表示する function CollaboratorsList({ userIds }: { userIds: string[] }) { const { getBatchUserDetails, isLoading } = useAdmin(); const [users, setUsers] = useState<Record<string, User>>({}); const [error, setError] = useState<unknown>(null); useEffect(() => { async function fetchUsers() { if (userIds.length > 0) { try { const fetchedUsers = await getBatchUserDetails(userIds); setUsers(fetchedUsers); } catch (err) { setError(err); } } } fetchUsers(); }, [userIds, getBatchUserDetails]); if (isLoading) return <div>Loading collaborators...</div>; if (error) return <div>Error loading collaborators</div>; return ( <div className="collaborators"> <h2>Project Collaborators</h2> <ul> {Object.entries(users).map(([userId, user]) => ( <li key={userId} className="collaborator-item"> <span className="name">{user.username}</span> <span className="email">{user.email ?? "Not set"}</span> </li> ))} </ul> </div> ); }
useAdmin フックを使用する前に、次のシナリオと制限事項を考慮してください。
URL.createObjectURL() を使用してプロフィール画像の blob URL を作成しますが、これらの URL の解放は処理しません。そのため、多数のプロフィール画像を読み込むと、メモリーリークが発生する可能性があります。利用側では、URL が不要になったときに URL.revokeObjectURL() を呼び出す必要があります。getBatchUserDetails を呼び出すと、空のオブジェクトを返し、リクエストを送信しません。呼び出し側では、フォールバック用のユーザーを期待するのではなく、空の結果を処理する必要があります。