Files
nextjs-todo-tutorial/src/components/TodoList.tsx

77 lines
1.9 KiB
TypeScript

import React, { useMemo } from 'react';
import TodoItem from './TodoItem';
type Todo = {
id: number;
text: string;
completed: boolean;
};
type FilterType = 'all' | 'active' | 'completed';
type TodoListProps = {
todos: Todo[];
filter: FilterType;
editingId: number | null;
editText: string;
onToggleTodo: (id: number) => void;
onStartEdit: (todo: Todo) => void;
onSaveEdit: () => void;
onCancelEdit: () => void;
onDeleteClick: (id: number) => void;
onEditTextChange: (text: string) => void;
};
const TodoList = React.memo(function TodoList({
todos,
filter,
editingId,
editText,
onToggleTodo,
onStartEdit,
onSaveEdit,
onCancelEdit,
onDeleteClick,
onEditTextChange,
}: TodoListProps) {
// フィルタリング処理をメモ化
const filteredTodos = useMemo(() => {
switch (filter) {
case 'active':
return todos.filter(todo => !todo.completed);
case 'completed':
return todos.filter(todo => todo.completed);
default:
return todos;
}
}, [todos, filter]);
return (
<div className="space-y-2">
{filteredTodos.length === 0 ? (
<p className="text-gray-500 text-center py-8">
{filter === 'active' && 'すべて完了しました!'}
{filter === 'completed' && '完了したTODOがありません'}
{filter === 'all' && 'TODOがありません'}
</p>
) : (
filteredTodos.map((todo) => (
<TodoItem
key={todo.id}
todo={todo}
isEditing={editingId === todo.id}
editText={editText}
onToggle={() => onToggleTodo(todo.id)}
onStartEdit={() => onStartEdit(todo)}
onSaveEdit={onSaveEdit}
onCancelEdit={onCancelEdit}
onDelete={() => onDeleteClick(todo.id)}
onEditTextChange={onEditTextChange}
/>
))
)}
</div>
);
});
export default TodoList;