3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js × Supabase で作る TODO アプリ

Posted at

はじめに

この記事は フィヨルドブートキャンプ Part 2 Advent Calendar 2024 の10日目の記事です。

フィヨルドブートキャンプのアドベントカレンダー2024には、以下の2つがあります:

昨日(12/9)は beta_chelsea さんのヒトは如何にしてGitの習得に至るのかを考え中でした。チーム開発に参加して git のことを実践的に学びたいと思いました。

成果物

Neomorphism デザインを取り入れた TODO アプリです。

成果物

🔖 目次

1. 自己紹介
2. 環境の準備
3. Supabase のセットアップ
4. アプリケーションの構築
5. 動的ルーティングでのタスク編集
6. Neomorphism デザインの適用と解説
7. おわりに

1. 自己紹介

フィヨルドブートキャンプで学習している Kazuma です。
フロントエンドについて学んでいます🖊
この記事では Next.js (14.2.18), React (18.2.0), Supabase (1.223.10) を使った TODO アプリを作成します。

完成するアプリの主な機能:

  • タスクの追加・削除
  • タスクの完了状態の切り替え
  • タスクテーブルのリセット
  • タスク編集 (動的ルーティング対応)

2. 環境の準備

必要なツール

  1. Node.js (16 以上)
  2. Next.js (14.2.18)
  3. Supabase CLI

プロジェクトの作成

npx create-next-app@14.2.18 todo-app
cd todo-app
npm install @supabase/supabase-js

Supabase をローカルで動作させるために CLI を使用してセットアップします。

npx supabase init
npx supabase start

npx supabase status

Supabase の URL と anon キーを .env.local に記載する

.env.local
NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=<anon_key>

3. Supabase のセットアップ

テーブル作成

Supabase の SQL エディタで以下のクエリを実行し、todos テーブルを作成します:

Supabase Studio内の SQL Editor
create table todos (
  id uuid primary key default gen_random_uuid(),
  task text not null,
  is_complete boolean default false,
  created_at timestamp default now()
);

4. アプリケーションの構築

app/page.tsx の解説

1. タスクの取得 (fetchTodos)

Supabase の todos テーブルからデータを取得してリストに表示します。

const fetchTodos = async () => {
  const { data, error } = await supabase
    .from('todos')
    .select('*')
    .order('created_at', { ascending: true });
  if (!error) setTodos(data || []);
};

2. タスクの追加 (addTodo)

入力されたタスクを Supabase に挿入し、リストを更新します。

const addTodo = async () => {
  if (!newTask.trim()) return;
  const { data } = await supabase
    .from('todos')
    .insert([{ task: newTask }])
    .select('*');
  setTodos((prev) => [...prev, ...(data || [])]);
  setNewTask('');
};

3. タスクの完了状態の切り替え (toggleComplete)

タスクの完了状態を反転させます。

const toggleComplete = async (id: string, currentState: boolean) => {
  const { error } = await supabase
    .from('todos')
    .update({ is_complete: !currentState })
    .eq('id', id);
  if (!error) {
    setTodos((prev) =>
      prev.map((todo) =>
        todo.id === id ? { ...todo, is_complete: !currentState } : todo
      )
    );
  }
};

5. 動的ルーティングでのタスク編集

動的ルーティングの設定

app/pages/edit/[id].tsx を作成して、動的ルーティングを設定します。
この仕組みにより、URL の id を元に特定のタスクを編集できます。

[id].tsx の解説

1. タスクの取得

URL パラメータから id を取得し、Supabase を使用して該当タスクを取得します。

const fetchTask = useCallback(async () => {
  const { data } = await supabase
    .from('todos')
    .select('task')
    .eq('id', id)
    .single();
  setTask(data?.task || '');
}, [id]);

2. タスクの更新

入力した新しいタスク名で該当タスクを更新します。

const updateTask = async () => {
  await supabase.from('todos').update({ task }).eq('id', id);
  router.push('/');
};

3. タスクの削除

削除ボタンをクリックすると、タスクが削除されてホームに戻ります。

const deleteTask = async () => {
  if (confirm('Are you sure you want to delete this task?')) {
    await supabase.from('todos').delete().eq('id', id);
    router.push('/');
  }
};

6. Neomorphism デザインの適用と解説

ここでは、アプリの UI に Neomorphism デザイン を取り入れる方法を詳しく解説します。

Neomorphism デザインの要点

Neomorphism デザインの基本原則は以下の通りです:

  1. 光と影:
    • 背景色に近い要素の色を選択。
    • 明るい影と暗い影を box-shadow で表現。
  2. エッジの柔らかさ:
    • border-radius を使用して要素に丸みを持たせます。
  3. トランジション効果:
    • インタラクティブな操作時にアニメーションを加えます。

プレビュー

See the Pen Untitled by Kazuma Naka (@Kazuma-Naka) on CodePen.

7. おわりに

この記事では、Next.js と Supabase を使用して作成した TODO アプリを作成する方法を解説しました。Next.js を使うと、動的ルーティングを簡単に設定でき、編集ページを実装したい際に活用できます。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?