1. 状態管理

Qwik フレームワークにおける状態管理に関して、具体的な例を用いて学びます。ここでは、シンプルな Todo リストアプリケーションを例に、状態の定義、更新、および状態を基にした UI のレンダリング方法を説明します。

Todo リストアプリケーション

目的

Todo リストアプリケーションを作成することで、Qwik における状態管理の概念を実際に体験します。ユーザーが新しいタスクを追加できる機能と、それらのタスクをリスト表示する機能を実装します。

実装ステップ

  1. Todo リストコンポーネントの作成:
    • TodoList コンポーネントを定義し、タスクのリストを状態として保持します。
    • 新しいタスクを追加する機能を実装します。
  2. 状態の定義と更新:
    • useStore フックを使用して、タスクリストの状態を管理します。
    • タスクを追加するアクションを定義し、そのアクションをフォームの送信イベントにバインドします。
  3. UI のレンダリング:
    • 状態に基づいてタスクリストを動的にレンダリングします。
    • 各タスクに対して、タスクの内容を表示する UI を定義します。

コード例

// src/components/TodoList.tsx
import { component$, useStore } from '@builder.io/qwik';

export const TodoList = component$(() => {
  const state = useStore({
    tasks: [],
    newTask: '',
  });

  return (
    <div>
      <h2>Todo List</h2>
      <form
        onSubmit$={(event) => {
          event.preventDefault();
          state.tasks.push(state.newTask);
          state.newTask = '';
        }}
      >
        <input
          type='text'
          value={state.newTask}
          onInput$={(event) => (state.newTask = event.target.value)}
        />
        <button type='submit'>Add Task</button>
      </form>
      <ul>
        {state.tasks.map((task) => (
          <li>{task}</li>
        ))}
      </ul>
    </div>
  );
});

2. グローバルな状態管理

Qwik フレームワークにおいて、サイト全体で参照および更新可能なグローバルな状態管理の概念と実践方法を学びます。具体的には、ユーザー認証状態(ログインしているかどうか)をアプリケーション全体で管理する例を通して説明します。

ユーザー認証状態の管理

目的

ユーザーがログインしているかどうかを追跡し、この情報をアプリケーション全体でアクセス可能にします。ログイン状態に基づいて、特定の UI コンポーネントを表示または非表示にする方法を示します。

実装ステップ

  1. グローバル状態の定義:
    • アプリケーション全体で共有される状態(この場合はユーザーのログイン状態)をuseStore フックを使って定義します。
  2. 状態の更新と参照:
    • ログインとログアウト機能を実装し、グローバル状態を更新します。
    • 状態に基づいて条件付きで UI コンポーネントを表示します。
  3. UI のレンダリング:
    • ログイン状態に基づいて、異なるコンポーネントやメッセージを表示します。

コード例

まず、グローバルな状態を管理するストアを定義します。

// src/store/userStore.ts
import { useStore } from '@builder.io/qwik';

export const useUserStore = () => {
  const store = useStore({
    isLoggedIn: false,
  });
  return store;
};

次に、ログイン機能を持つコンポーネントを作成します。

// src/components/LoginButton.tsx
import { component$ } from '@builder.io/qwik';
import { useUserStore } from '../store/userStore';

export const LoginButton = component$(() => {
  const userStore = useUserStore();

  return (
    <button
      onClick$={() => {
        userStore.isLoggedIn = !userStore.isLoggedIn; // 簡単なトグルで実装
      }}
    >
      {userStore.isLoggedIn ? 'Log Out' : 'Log In'}
    </button>
  );
});

最後に、ログイン状態に基づいて表示を変えるコンポーネントを実装します。

// src/components/UserGreeting.tsx
import { component$ } from '@builder.io/qwik';
import { useUserStore } from '../store/userStore';

export const UserGreeting = component$(() => {
  const userStore = useUserStore();

  return (
    <div>
      {userStore.isLoggedIn ? (
        <h2>Welcome back, User!</h2>
      ) : (
        <h2>Please log in.</h2>
      )}
    </div>
  );
});

3. localStorage を使用した状態の永続化

Qwik フレームワークにおけるグローバルな状態管理では、ページリロード時に状態が初期化されてしまいます。これは、クライアントサイドの JavaScript で管理される状態が、新しいページリクエストでリセットされるためです。しかし、バックエンドのデータベースを使用せずに状態を永続化する方法があります。主な方法の一つは、Web Storage API(localStorage または sessionStorage)を利用することです。

localStorageを使用すると、ブラウザが閉じられた後やページがリロードされた後もデータを保存できます。localStorageはキーと値のペアでデータを保存し、そのデータは文字列形式でなければなりません。したがって、オブジェクトを保存する場合は、JSON.stringifyでシリアライズし、取り出す際にはJSON.parseでデシリアライズする必要があります。

Qwik での具体的な実装例

以下は、Qwik フレームワークを使用して、ユーザーのログイン状態をlocalStorageを使って永続化する例です。

ログイン状態の永続化
// src/components/LoginButton.tsx
import { component$, useStore } from '@builder.io/qwik';

export const LoginButton = component$(() => {
  const state = useStore({
    isLoggedIn: JSON.parse(localStorage.getItem('isLoggedIn') || 'false'),
  });

  const toggleLoginState = () => {
    const newState = !state.isLoggedIn;
    state.isLoggedIn = newState;
    localStorage.setItem('isLoggedIn', JSON.stringify(newState));
  };

  return (
    <button onClick$={toggleLoginState}>
      {state.isLoggedIn ? 'Log Out' : 'Log In'}
    </button>
  );
});

このコンポーネントでは、useStoreを使ってisLoggedIn状態を管理しています。localStorageからこの状態を読み込むことで、ページリロード後もユーザーのログイン状態を維持できます。ボタンがクリックされると、toggleLoginState関数が呼び出され、状態が反転し、新しい状態がlocalStorageに保存されます。

注意点

  • localStorageはクライアントサイドでのみアクセス可能です。サーバーサイドレンダリング(SSR)のコンテキストでは利用できませんので、クライアントサイドのコードでのみ使用してください。
  • セキュリティの観点から、機密情報はlocalStorageに保存しないようにしてください。localStorageはクロスサイトスクリプティング(XSS)攻撃によって読み取られる可能性があります。

この方法により、バックエンドのデータベースを使わずに、Qwik フレームワークで管理している状態の永続化を実現できます。