React サスペンスを使って Next.js 13 でローディング UI を作成する方法

ローディング UI とビジュアル要素は、ウェブやモバイルアプリケーションの重要なコンポーネントです。ユーザーエクスペリエンスとエンゲージメントを向上させる上で重要な役割を果たします。このような手がかりがなければ、ユーザーはアプリケーションが適切に機能しているのか、正しい操作を行ったのか、操作が処理されているのかわからず、混乱したり不安になったりするかもしれません。

進行中の処理を示すさまざまなビジュアル手がかりをユーザーに提供することで、あらゆる形態の不確実性や不満を効果的に軽減し、最終的にはユーザーがアプリケーションを途中で終了することを防ぐことができます。

ローディング UI がパフォーマンスとユーザーエクスペリエンスに与える影響

ヤコブ・ニールセンのユーザーインターフェースデザインの10のヒューリスティックは、現在のシステムの状態がエンドユーザーに可視化されていることを確認することの重要性を強調しています。この原則は、ローディング UI やその他のフィードバック UI 要素などのユーザーインターフェースコンポーネントが、進行中のプロセスと必要な時間枠内でユーザーに適切なフィードバックを迅速に提供する必要があることを強調しています。

ローディング UI は、アプリケーションの全体的なパフォーマンスとユーザーエクスペリエンスを形作る上で重要な役割を果たします。パフォーマンスの観点から見ると、効果的なローディング画面を実装することで、ウェブアプリケーションの速度と応答性を大幅に向上させることができます。

理想的には、ローディング UI を効果的に活用することで、非同期コンテンツのロードが可能になります。これにより、特定のコンポーネントがバックグラウンドでロードされている間、ページ全体がフリーズすることを防ぎ、本質的によりスムーズなブラウジングエクスペリエンスを実現します。

さらに、進行中のプロセスを明確に視覚的に示すことで、ユーザーはコンテンツの取得を辛抱強く待つようになります。

Next.js 13 で React サスペンスを使い始める

サスペンスは、データの取得など、バックグラウンドで実行されている非同期操作を管理する React コンポーネントです。簡単に言うと、このコンポーネントを使用すると、目的の子コンポーネントがマウントされて必要なデータがロードされるまで、フォールバックコンポーネントをレンダリングできます。

サスペンスの仕組みの例をご紹介します。API からデータを取得するコンポーネントがあるとします。

export default function Todos() {const data = fetchData() {//fetch data...return data;};return  {data.title} }// the fallback componentexport default function Loading() {return Loading data ... }

サスペンスは、Todosコンポーネントのコンテンツのロードが完了してレンダリングの準備ができるまで、Loadingコンポーネントを表示します。これを実現するためのサスペンスの構文を以下に示します。

import { Suspense } from 'react';function App() {return ();}

Next.js 13 は React サスペンスをサポート

Next.js 13 は、アプリディレクトリ機能を通じてサスペンスのサポートを追加しました。本質的に、アプリディレクトリを使用すると、特定のルートのページファイルを専用のフォルダーに含めて整理することができます。

このルートディレクトリには、loading.jsファイルを含めることができます。Next.js はこのファイルをフォールバックコンポーネントとして使用して、データを含む子コンポーネントをレンダリングする前にローディング UI を表示します。

では、デモ ToDo アプリケーションを構築して、Next.js 13 に React サスペンスを統合してみましょう。

このプロジェクトのコードは GitHub リポジトリにあります。

Next.js 13 プロジェクトを作成する

DummyJSON API エンドポイントから ToDo のリストを取得するシンプルなアプリケーションを構築します。はじめに、以下のコマンドを実行して Next.js 13 をインストールします。

npx create-next-app@latest next-project --experimental-app

Todos ルートを定義する

src/appディレクトリ内に新しいフォルダーを作成し、Todosという名前を付けます。このフォルダー内に新しいpage.jsファイルを追加し、以下のコードを含めます。

async function Todos() {async function fetchTodos() {let res = await fetch("https://dummyjson.com/todos");const todosData = await res.json();return todosData}const {todos} = await fetchTodos();async function wait(ms) {return new Promise(resolve => setTimeout(resolve, ms));}await wait(3000);return ({todos.slice(0, 10).map((todo) => ( {todo.todo} ))});}export default Todos;

非同期関数Todosは、DummyJSON API から ToDo のリストを取得します。次に、取得した ToDo の配列をマップして、ブラウザページに ToDo のリストをレンダリングします。

さらに、コードには非同期wait関数があり、遅延をシミュレートします。これにより、ユーザーが取得した ToDo を表示する前に特定の期間ローディング UI を表示できるシナリオが作成されます。

より現実的なユースケースでは、遅延をシミュレートするのではなく、アプリケーション内の処理アクティビティ、データベースからのデータの取得、API の使用、さらには API の応答時間の遅延などの状況が、わずかな遅延を引き起こす可能性があります。

Next.js アプリケーションに React サスペンスを統合する

app/layout.jsファイルを開き、Next.js の定型コードを以下のコードに更新します。

import React, { Suspense } from 'react';import Loading from '@/app/Todos/loading';export const metadata = {title: 'Create Next App',description: 'Generated by create next app',}export default function RootLayout({ children }) {return ({children})}

Next.js 13 のapp/layout.jsファイルは、アプリケーションのレイアウトの全体的な構造と動作を定義する中央レイアウトコンポーネントとして機能します。この場合、childrenプロパティをSuspenseコンポーネントに渡すことで、レイアウトがアプリケーションのコンテンツ全体のラッパーになることを保証します。

Suspenseコンポーネントは、子コンポーネントが非同期にコンテンツをロードしている間はLoadingコンポーネントをフォールバックとして表示します。これにより、コンテンツがバックグラウンドで取得または処理されていることをユーザーに示します。

ホームルートファイルを更新する

app/page.jsファイルを開き、Next.js の定型コードを削除して、以下のコードを追加します。

import React from 'react';import Link from "next/link";function Home () {return (Next.js 13 React サスペンスのロード例Todo を取得)}export default Home;

loading.js ファイルを作成する

最後に、app/Todosディレクトリ内にloading.jsファイルを作成します。このファイル内に、以下のコードを追加します。

export default function Loading() {return Loading data ... }

ローディング UI コンポーネントに最新のスピナーを追加する

作成したローディング UI コンポーネントは非常に基本的なものです。必要に応じて、スケルトン画面を追加することもできます。または、Next.js アプリケーションで Tailwind CSS を使用してカスタムローディングコンポーネントを作成してスタイルを設定することもできます。次に、React Spinners などのパッケージによって提供されるスピナーなどのユーザーフレンドリーなローディングアニメーションを追加します。

このパッケージを使用するには、プロジェクトにインストールします。

npm install react-loader-spinner --save

次に、loading.jsファイルを以下のように更新します。

"use client"import { RotatingLines} from 'react-loader-spinner'function Loading() {return (Todo をロード中 ...);}export default Loading;

これで、ローディング UI に Todo データを取得している間、ローディングメッセージが表示され、回転するラインのスピナーアニメーションがレンダリングされて、進行中の処理が示されます。

ローディング UI でユーザーエクスペリエンスを改善する

ローディング UI をウェブアプリケーションに組み込むことで、ユーザーエクスペリエンスを大幅に向上させることができます。非同期操作中にユーザーに視覚的な手がかりを提供することで、ユーザーの不安や不確実性を効果的に最小限に抑え、結果的にエンゲージメントを最大化することができます。