From 5c39ad7bd4a95bb037ed82d98228c1fb39825521 Mon Sep 17 00:00:00 2001 From: Joseph McCullough Date: Thu, 13 Jun 2024 10:49:02 -0500 Subject: [PATCH] Update TodoList.jsx to use useDispatch --- .../components/islands/TodoList.jsx | 94 +++++++++++++------ 1 file changed, 63 insertions(+), 31 deletions(-) diff --git a/examples/hello-world/hello-world-project/hello-world-app/components/islands/TodoList.jsx b/examples/hello-world/hello-world-project/hello-world-app/components/islands/TodoList.jsx index b988035..2a2a510 100644 --- a/examples/hello-world/hello-world-project/hello-world-app/components/islands/TodoList.jsx +++ b/examples/hello-world/hello-world-project/hello-world-app/components/islands/TodoList.jsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useReducer, useState } from 'react'; import Button from './Button.jsx'; import styles from '../../styles/todo.module.css'; @@ -10,7 +10,6 @@ import styles from '../../styles/todo.module.css'; // - Examples of various ways to do conditional styling based on incoming props // or module fields (inline comments below) -let id = 0; const todoSortByCompleted = (todoA, todoB) => { if (todoA.completed && todoB.completed) { // Earlier IDs correspond to higher place in the list @@ -21,17 +20,62 @@ const todoSortByCompleted = (todoA, todoB) => { return todoA.id - todoB.id; }; -const initialTodosMapped = (todos) => - todos.map((initialTodo, i) => ({ - id: `default-${i}`, - key: `default-${i}`, - ...initialTodo, - })); +const initialize = (initialTodos) => { + return { + nextId: 0, + todos: initialTodos.map((initialTodo, i) => ({ + id: `default-${i}`, + key: `default-${i}`, + ...initialTodo, + })), + }; +}; + +const reducer = (state, action) => { + switch (action.action) { + case 'ADD_TODO': { + const todoText = action.value; + return { + todos: [ + ...state.todos, + { + id: state.nextId, + key: state.nextId, + text: todoText, + completed: false, + }, + ].sort(todoSortByCompleted), + nextId: state.nextId + 1, + }; + } + case 'TOGGLE_TODO': { + const updatedTodoId = action.value; + return { + ...state, + todos: state.todos + .map((todo) => + todo.id === updatedTodoId + ? { ...todo, completed: !todo.completed } + : todo, + ) + .sort(todoSortByCompleted), + }; + } + case 'REMOVE_TODO': { + const todoToRemoveId = action.value; + return { + ...state, + todos: state.todos.filter((todo) => todo.id !== todoToRemoveId), + }; + } + default: + return state; + } +}; function TodoItem({ todo, onRemove, onUpdate }) { const handleTodoCompleteClick = () => { - const updatedTodo = { ...todo, completed: !todo.completed }; - onUpdate(updatedTodo); + onUpdate(todo.id); }; const handleTodoRemoveClick = () => { @@ -48,7 +92,7 @@ function TodoItem({ todo, onRemove, onUpdate }) { todo.completed ? styles.complete : styles.notComplete }`} > - + {todo.text} {todo.dateAdded ? ( {todo.dateAdded} @@ -64,37 +108,25 @@ function TodoItem({ todo, onRemove, onUpdate }) { } function TodoList({ initialTodos = [], buttonColor, completeTodoOpacity }) { - const [todoList, setTodoList] = useState(() => - initialTodosMapped(initialTodos) - ); + const [state, dispatch] = useReducer(reducer, initialTodos, initialize); const [todoInput, setTodoInput] = useState(''); + const todoList = state.todos; - const addTodo = (todo) => { - todo['id'] = id; - todo['key'] = id; - id += 1; - - setTodoList([...todoList, todo].sort(todoSortByCompleted)); + const addTodo = (todoText) => { + dispatch({ action: 'ADD_TODO', value: todoText }); }; const handleRemoveTodo = (todoId) => { - setTodoList(todoList.filter((todo) => todo.id !== todoId)); + dispatch({ action: 'REMOVE_TODO', value: todoId }); }; - const handleUpdateTodo = (updatedTodo) => { - setTodoList( - todoList - .map((todo) => (todo.id === updatedTodo.id ? updatedTodo : todo)) - .sort(todoSortByCompleted), - ); + const handleUpdateTodo = (updatedTodoId) => { + dispatch({ action: 'TOGGLE_TODO', value: updatedTodoId }); }; const handleAddTodoClick = () => { - const todo = { text: todoInput, completed: false }; - - addTodo(todo); + addTodo(todoInput); setTodoInput(''); - return todo; }; const handleTodoInput = (e) => setTodoInput(e.target.value);