1
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?

Reactのtodoリスト、localstrage使用

Last updated at Posted at 2025-03-09

Reactで3ページ構成のlacalStorageを使用したTodoアプリを作ってみて
細かい機能をまとめようと書いてみました

lacalStorageとは

ローカルストレージは、キーと値の形式でデータを保存するブラウザAPIの一部で、ページを再読み込みしてもデータが保持されるのが特徴です。

基本ステップ

//値を保存する localStorage.setItem(key, value)を使用して、値をローカルストレージに保存します。
localStorage.setItem("username", "Takasuki");

// 値を取得する localStorage.getItem(key)で、保存された値を取得します。
const username = localStorage.getItem("username");
console.log(username); // "Tokumei"

//値を削除する localStorage.removeItem(key)で特定のキーを削除します。
localStorage.removeItem("username");

// すべてのデータをクリアする 全てのデータを削除するにはlocalStorage.clear()を使います。
localStorage.clear();

実際の使用

Todoリストに追加の実装

まず定数を設定してローカルストレージの準備

const navigate = useNavigate();
const handleAddTask = (newTask) => {
    const storedTasks = JSON.parse(localStorage.getItem('tasks')) || [];
    const updatedTasks = [...storedTasks, { id: storedTasks.length + 1, ...newTask }];
    
    localStorage.setItem('tasks', JSON.stringify(updatedTasks));
    navigate('/');
  };

作成した関数を設定
ついでに内容をコンポーネントにTaskFormを作成して引っ張ってくる

import TaskForm from '../components/TaskForm';
  return (
      <div className="w-full max-w-lg bg-white shadow-md rounded-lg p-6">
        <TaskForm onAddTask={handleAddTask} />
      </div>
  );

components/TaskFormに以下を記述してもってこれるように

import React, { useState } from 'react';

const TaskForm = ({ onAddTask }) => {
const [title, setTitle] = useState('');
const [description, setDescription] = useState('');

const handleSubmit = (e) => {
  e.preventDefault();
  if (!title.trim() || !description.trim()) return;

  onAddTask({ title, description });
  setTitle('');
  setDescription('');
};

return (
  <form onSubmit={handleSubmit}>
    <div className='flex justify-between'>
      <label >タイトル</label>
      <input
        type="text"
        value={title}
        onChange={(e) => setTitle(e.target.value)}
        required
        className='border w-2/3'
      />
    </div>
    <div className='flex justify-between'>
      <label>詳細</label>
      <input
        type="text"
        value={description}
        onChange={(e) => setDescription(e.target.value)}
        required
        className=' border w-2/3'
      />
    </div>
    <button type="submit" className=' block mx-auto' >タスクの追加</button>
  </form>
);
};

export default TaskForm;

これで追加ができるはずです

一覧の表示

Home画面より一覧表示を設定、詳細をcomponents/TaskListより記述して引っ張ってきてます
reactのルートについては別途記入します

import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import TaskList from "../components/TaskList";

  const [tasks, setTasks] = useState([]);

  useEffect(() => {
    const storedTasks = JSON.parse(localStorage.getItem("tasks")) || [];
    setTasks(storedTasks);
  }, []);

  return (
    <div className="min-h-screen bg-gray-100 flex flex-col items-center p-6">
      <h1 className="text-3xl font-bold text-gray-800 mb-6">To-Do リスト</h1>

      <div className="w-full max-w-2xl bg-white shadow-md rounded-lg p-4">
        <TaskList tasks={tasks} />
      </div>

      <Link
        to="/add"
        className="mt-6 px-6 py-3 bg-blue-500 text-white font-semibold rounded-lg shadow hover:bg-blue-600 transition"
      >
        タスクを追加
      </Link>
    </div>
  );
};

export default Home;

マップ構文より順々にtasksからidとdescriptonを引っ張ってこれるようにしてます

import React from 'react';
import { Link } from 'react-router-dom';

const TaskList = ({ tasks }) => {
  return (
    <div>
      <h2>Task List</h2>
      {tasks.map((task) => (
        <div key={task.id}>
          <Link to={`/task/${task.id}`}>
            <h3>{task.title}</h3>
          </Link>
          <p>{task.description}</p>
        </div>
      ))}
    </div>
  );
};

export default TaskList;

削除機能

詳細ページで削除機能を入れてみました

import React, { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import TaskDetail from '../components/TaskDetail';

const TaskDetailPage = () => {
  const { id } = useParams();
  const navigate = useNavigate();
  const [task, setTask] = useState(null);

  useEffect(() => {
    const storedTasks = JSON.parse(localStorage.getItem('tasks')) || [];
    const foundTask = storedTasks.find((t) => t.id === Number(id));
    setTask(foundTask);
  }, [id]);

  // タスク削除関数
  const handleDeleteTask = () => {
    const storedTasks = JSON.parse(localStorage.getItem('tasks')) || [];
    const updatedTasks = storedTasks.filter((t) => t.id !== Number(id));
    localStorage.setItem('tasks', JSON.stringify(updatedTasks));

    navigate('/'); // 削除後にタスク一覧へリダイレクト
  };

  return (
    <div className="min-h-screen bg-gray-100 flex flex-col items-center p-6">
      <h2 className="text-2xl font-bold text-gray-800 mb-6">タスクの詳細</h2>

      <div className="w-full max-w-lg bg-white shadow-md rounded-lg p-6">
        {task ? (
          <>
            <TaskDetail task={task} />
            <button
              onClick={handleDeleteTask}
              className="mt-6 px-6 py-3 bg-red-500 text-white font-semibold rounded-lg shadow hover:bg-red-600 transition"
            >
              削除
            </button>
          </>
        ) : (
          <p className="text-gray-500">タスクが見つかりません</p>
        )}
      </div>

      <button
        onClick={() => navigate('/')}
        className="mt-6 px-6 py-3 bg-gray-500 text-white font-semibold rounded-lg shadow hover:bg-gray-600 transition"
      >
        戻る
      </button>
    </div>
  );
};

export default TaskDetailPage;

components/TaskDetailは以下の記述

import React from 'react';

const TaskDetail = ({ task }) => {
  if (!task) return <p>Task not found</p>;

  return (
    <div>
      <h2>{task.title}</h2>
      <p>{task.description}</p>
    </div>
  );
};

export default TaskDetail;

大本

いかにgithubリンクを載せたので大本確認したい人はどうぞ

1
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
1
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?