ユースケース開発React アプリケーションのためのOSDKチュートリアル:高度なToDoアプリケーションUseLearningTaskフック

注: 以下の翻訳の正確性は検証されていません。AIPを利用して英語版の原文から機械的に翻訳されたものです。

useLearningTask フック

useLearningTask フックは、高度な To-Do アプリケーションで学習タスクデータを取得および管理する機能を提供するカスタム React フックです。基本的なタスクデータに、ユーザー情報、メディアコンテンツ、メタデータを追加します。

このフックは、さまざまなメディアの種類やバイナリコンテンツを処理するパターンを使用し、Result 型によるエラー処理と Blob URL のリソース管理を示します。アプリケーションのオントロジーとシームレスに統合しながら、コンポーネントにシンプルなインターフェースを提供します。

useLearningTask の参照コードを表示する。

主な機能

  • React の useCallback を使用して関数をメモ化し、不要な再レンダリングを防止
  • SWR(stale-while-revalidate)のキャッシュとカスタム再検証オプションを活用してパフォーマンスを最適化
  • バイナリメディアコンテンツ用の Blob URL 管理を実装
  • MIME タイプに基づくインテリジェントなメディアの種類の検出を提供
  • 複数のコンテンツ配信方式(埋め込みとリンク)に対応
  • Result 型を使用して堅牢なエラー処理を実現
  • useAdmin を通じたバッチリクエストでユーザーデータを効率的に取得

useLearningTask の構造

インターフェース定義

Copied!
1 2 3 4 5 6 7 interface LearningTaskEnriched { osdkLearningTask: osdkLearningTask.OsdkInstance; mediaUrl: string; createdBy: User; assignedTo: User; mediaType: SupportedMediaType; }

このインターフェースは、SDK の学習タスクインスタンスに、ユーザーオブジェクト、メディアコンテンツの URL、検出されたメディアの種類を組み合わせ、コンポーネント用の包括的なデータ構造を作成します。

データ取得

useLearningTask フックは、SWR のデータ取得機能と、次の処理を行うカスタム取得関数を使用します。

  1. fetchOneWithErrors を使用して特定の学習タスクをクエリし、堅牢なエラー処理を実現します
  2. タスクの設定に基づいてメディアコンテンツを処理します。
    • mediaReference が存在する場合は、バイナリコンテンツを取得して Blob URL を作成します
    • contentUrl が存在する場合は、外部リンクとして使用します
    • 利用可能なメディアがない場合に対応します
  3. MIME タイプの検出を使用してメディアの種類を特定します
  4. バッチリクエストを通じて、タスクの作成者と担当者のユーザー詳細を取得します
  5. すべてのデータを LearningTaskEnriched 構造にまとめます
Copied!
1 2 3 4 5 6 const fetcher = useCallback(async () => { const learningTaskResult = await client(osdkLearningTask).fetchOneWithErrors(task.osdkTask.$primaryKey as string); // エラー処理とデータ処理 // ... return learningTaskEnriched; }, [client, task.osdkTask.$primaryKey, getBatchUserDetails]);

メディアの種類の検出

このフックには、MIME タイプからメディアの種類を特定するヘルパー関数が含まれています。

Copied!
1 2 3 4 5 6 7 8 const getMediaTypeFromMimeType = (mimeType: string): SupportedMediaType => { if (/application\/pdf/.test(mimeType)) { return SupportedMediaType.PDF; } else if (/image\/(jpeg|png|gif)/.test(mimeType)) { return SupportedMediaType.IMAGE; } // ...その他の種類の検出 };

このユーティリティは正規表現を使用して MIME タイプを一般的なメディア形式と照合し、さまざまな種類の学習コンテンツを一貫した方法で分類します。

戻り値

useLearningTask フックは、次の構造を持つオブジェクトを返します。

Copied!
1 2 3 4 5 6 7 { learningTask: LearningTaskEnriched | undefined; // 情報が付加された学習タスク(読み込まれていない場合は undefined) isLoading: boolean; // 初回のデータ読み込み中は true isValidating: boolean; // バックグラウンドでの再検証中は true isError: any; // リクエストに失敗した場合のエラーオブジェクト metadata: ObjectMetadata | undefined; // 学習タスクのオブジェクトタイプに関するメタデータ }

実装

メディアの種類の列挙

useLearningTask フックは、さまざまな種類のメディアを表す文字列リテラルの共用体型を定義します。

Copied!
1 2 3 4 5 6 7 8 9 export const SupportedMediaType = { PDF: "PDF", IMAGE: "IMAGE", LINK: "LINK", VIDEO: "VIDEO", NONE: "NONE" } as const; export type SupportedMediaType = typeof SupportedMediaType[keyof typeof SupportedMediaType];

Result 型のパターン

このフックは、エラー処理にオントロジー SDK の Result 型を使用します。

Copied!
1 2 3 4 5 6 7 const learningTaskResult: Result<Osdk.Instance<osdkLearningTask>> = await client(osdkLearningTask).fetchOneWithErrors(task.osdkTask.$primaryKey as string); if (learningTaskResult.error) { throw new Error(learningTaskResult.error.message); } const learningTask = learningTaskResult.value;

このパターンは次の処理を行います。

  1. 成功状態とエラー状態の両方を単一の戻り値で表します
  2. データにアクセスする前に明示的なエラーチェックを行えるようにします
  3. 構造化されたエラー情報を提供してエラー処理を改善します
  4. 従来の try/catch よりも堅牢な方法を実現します

Blob URL の管理

このフックは、メディアコンテンツの Blob URL を管理します。

Copied!
1 2 3 const response = await learningTask.mediaReference.fetchContents(); const blob: Blob | undefined = await response.blob(); const mediaUrl = blob ? URL.createObjectURL(blob) : "";

このパターンは次の処理を行います。

  1. バイナリコンテンツを Response オブジェクトとして取得します
  2. レスポンスを Blob に変換します
  3. メディア要素で使用するための Blob の一時 URL を作成します
  4. Blob が未定義になる可能性があるエッジケースを適切に処理します

外部パッケージ

次の外部パッケージを useLearningTask フックと併用できます。

useSWR

用途: データ取得、キャッシュ、状態管理 利点:

  • 学習タスクデータを取得してキャッシュする洗練された方法を提供します
  • 読み込み状態とエラー状態を自動的に処理します
  • 組み込みの再検証戦略を提供します
  • 設定可能な再検証設定でパフォーマンスを最適化します
  • インテリジェントなキャッシュでネットワークリクエストを削減します

@osdk/client & @osdk/react

用途: バックエンドのデータサービスとやり取りするためのオントロジー SDK クライアント 利点:

  • データモデル用の型安全なインターフェースを提供します
  • Result 型を使用した構造化データクエリを可能にし、適切なエラー処理を実現します
  • メディアコンテンツの取得とメタデータへのアクセスをサポートします
  • オブジェクトタイプのメタデータを取得するユーティリティを提供します
  • クライアントインスタンスにアクセスするための useOsdkClient などのフックを公開します

@advanced-to-do-application/sdk

用途: 事前定義されたデータ型を持つ、アプリケーション固有の SDK 利点:

  • 学習タスク固有のデータモデル(osdkLearningTask)を含みます
  • 学習タスクのプロパティと Media Reference への型付きアクセスを提供します
  • アプリケーション全体で一貫した型の強制を可能にします
  • アプリケーションのオントロジーモデルをサポートします

@osdk/foundry.admin

用途: ユーザーデータ型用の Foundry Admin SDK

利点:

  • createdBy フィールドと assignedTo フィールドで使用する User 型を提供します
  • ユーザーデータの型が Foundry Admin API と一貫することを保証します

使用例

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 76 77 78 79 80 81 82 83 84 85 86 87 88 import useLearningTask, { SupportedMediaType } from '../dataServices/useLearningTask'; import type { ITask } from '../dataServices/useTasks'; function LearningTaskViewer({ task }: { task: ITask }) { const { learningTask, isLoading, isError, metadata } = useLearningTask(task); if (isLoading) return <div>Loading learning materials...</div>; if (isError) return <div>Error loading content: {isError.message}</div>; if (!learningTask) return <div>No learning content available</div>; // メディアの種類に応じて適切に表示します const renderMedia = () => { switch (learningTask.mediaType) { case SupportedMediaType.PDF: return ( <div className="pdf-viewer"> <iframe src={`${learningTask.mediaUrl}#toolbar=0`} title="PDF Content" width="100%" height="500px" /> </div> ); case SupportedMediaType.IMAGE: return ( <div className="image-viewer"> <img src={learningTask.mediaUrl} alt="Learning content" className="learning-image" /> </div> ); case SupportedMediaType.VIDEO: return ( <div className="video-player"> <video src={learningTask.mediaUrl} controls width="100%" /> </div> ); case SupportedMediaType.LINK: return ( <div className="external-link"> <a href={learningTask.mediaUrl} target="_blank" rel="noopener noreferrer" > Open learning resource </a> </div> ); default: return <div>No media content available</div>; } }; return ( <div className="learning-task-viewer"> <h2>{learningTask.osdkLearningTask.title}</h2> <div className="content-section"> <div className="content-type-badge">{learningTask.mediaType}</div> {renderMedia()} </div> <div className="description-section"> <h3>Description</h3> <p>{learningTask.osdkLearningTask.description || "No description provided"}</p> </div> <div className="people-section"> <div className="assigned-to"> <span>Assigned to: </span> <span>{learningTask.assignedTo?.username ?? "Unassigned"}</span> </div> <div className="created-by"> <span>Created by: </span> <span>{learningTask.createdBy?.username ?? "Unknown"}</span> </div> </div> </div> ); }

エッジケースと制限事項

useLearningTask フックを使用する前に、次のシナリオと制限事項を考慮してください。

  • メモリー管理: このフックは Blob URL を作成しますが、現在はクリーンアップを実装していません。本番環境のアプリケーションでは、メモリーリークを防ぐため、これらの URL が不要になったときに URL.revokeObjectURL() で解放してください。
  • メディアの種類の検出: メディアの種類の検出は MIME タイプに基づいており、考えられるすべての形式に対応しているとは限りません。デフォルトのフォールバックは NONE ですが、一部の特殊なメディア形式には適切でない場合があります。
  • メディアのエラー処理: このフックはタスク取得時のエラーを処理しますが、メディアコンテンツの取得や処理に特化したエラー処理はありません。そのため、メディアの読み込みに失敗すると、未処理の例外が発生する可能性があります。
  • ネットワークの依存関係: このフックは、互いに依存する複数のネットワークリクエスト(タスクデータ、ユーザーデータ、メディアコンテンツ)を行います。ネットワークの状態が悪い場合、連鎖的な失敗やタイムアウトにつながる可能性があります。
  • 大きなメディアファイル: 大きなメディアファイルでは、Blob 全体をメモリーに読み込む方法がパフォーマンスの問題を引き起こす可能性があります。大きなファイルには、ストリーミングやプログレッシブ読み込みの実装を検討してください。
  • ブラウザーの互換性: Blob URL のサポートとメディア再生機能は、ブラウザーによって異なります。ブラウザー間の完全な互換性を確保するには、追加のフォールバック戦略が必要になる場合があります。
  • メディアのキャッシュ戦略がない: SWR はタスクデータをキャッシュしますが、メディアコンテンツ自体に特化したキャッシュ戦略はありません。メディアの Blob 専用のキャッシュ機構を実装すると、パフォーマンスを改善できる可能性があります。