react-serverでは、ページやコンテンツを更新するための方法が2つ提供されています。
宣言的なアプローチの<Refresh>コンポーネントと、命令的なアプローチのrefresh()関数です。
一見似ているように見えるこの2つの更新方法ですが、実際どのような違いがありのかまとめてみました。
2つの更新方法
まず、それぞれの基本的な使い方を見てみましょう:
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 | // 方法1: Refreshコンポーネントを使用 import { Refresh } from "@lazarv/react-server/navigation"; function RefreshButtonUsingComponent() { return ( <div> <Refresh>更新する</Refresh> </div> ); } // 方法2: refresh関数を使用 import { useClient } from "@lazarv/react-server/client"; import { startTransition } from "react"; function RefreshButtonUsingFunction() { const { refresh } = useClient(); return ( <div> <button onClick={() => startTransition(async () => refresh())}> 更新する </button> </div> ); } |
一見すると似たような機能に見えますが、実際には重要な違いがあります。
1. コンポーネント vs 関数
最も明確な違いは、一方がReactコンポーネントであり、もう一方が関数であるという点です。
- <Refresh>:ユーザーインターフェースを構成するReactコンポーネント。宣言的なアプローチ
- refresh():プログラムから呼び出す関数。命令的なアプローチ
2. 使用方法と柔軟性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // Refreshコンポーネント - シンプルに使える <Refresh>クリックして更新</Refresh> // refresh関数 - より多くのコントロールが可能 const { refresh } = useClient(); // 条件付き更新 const conditionalRefresh = () => { if (hasChanges) { startTransition(async () => refresh()); } }; // 特定のアウトレットのみ更新 const refreshDashboard = () => { startTransition(async () => refresh("dashboardOutlet")); }; // 他の処理と組み合わせる const saveAndRefresh = async () => { await saveData(); startTransition(async () => refresh()); showNotification("保存しました"); }; |
refresh()関数は柔軟性が高く、より複雑なシナリオに対応できます。
3. トランジションの扱い
<Refresh>コンポーネントは内部でReactのトランジションを自動的に処理しますが、refresh()関数を使用する場合は、通常自分でstartTransitionを使ってトランジションを開始する必要があります。
| // Refreshコンポーネント - トランジションは内部で処理される <Refresh>更新</Refresh> // refresh関数 - 自分でトランジションを開始する <button onClick={() => startTransition(async () => refresh())}> 更新 </button> |
これにより、refresh()関数を使用する場合、トランジションのタイミングをより細かく制御できます。
ユースケース:どちらを選ぶべき?
それぞれの方法が適している状況を考えてみます。
<Refresh>コンポーネントが適している場合
- シンプルな「更新ボタン」が欲しい場合
- マークアップが中心で、複雑なロジックが不要な場合
- React Serverのデフォルトの動作で十分な場合
- JSXの中で直感的に使いたい場合
| function SimplePage() { return ( <div className="page-container"> <header> <h1>マイダッシュボード</h1> <Refresh>更新</Refresh> </header> <main> {/* ページコンテンツ */} </main> </div> ); } |
refresh()関数が適している場合
- 他のロジックと組み合わせる必要がある場合
- 条件付きで更新したい場合
- 特定のアウトレットだけを更新したい場合
- カスタムUIと組み合わせたい場合
- プログラムで更新のタイミングを制御したい場合
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 | function ComplexDashboard() { const { refresh } = useClient(); const [isLoading, setIsLoading] = useState(false); const handleRefresh = async () => { setIsLoading(true); // 先にバックエンドAPIからデータを取得 await fetchLatestData(); // その後ページを更新 startTransition(async () => { await refresh(); setIsLoading(false); }); // 分析データを送信 trackEvent("dashboard_refreshed"); }; return ( <div className="dashboard"> <button onClick={handleRefresh} disabled={isLoading} className={isLoading ? "btn-loading" : "btn-normal"} > {isLoading ? "更新中..." : "最新データに更新"} </button> {/* ダッシュボードコンテンツ */} </div> ); } |
まとめ
React Serverにおける2つの更新方法は、同じ機能をベースとしながらも、異なるユースケースに合わせて最適化されています。
- <Refresh>コンポーネント:シンプルさと宣言的なアプローチを重視
- refresh()関数:柔軟性と制御性を重視
より高度なパフォーマンス最適化やユーザーエクスペリエンス向上のためには、refresh()関数とstartTransitionを組み合わせた方法が多くの場合に適していそうです。
しかし、シンプルなUI要素としては<Refresh>コンポーネントの直感的に使いやすいです。