사용자가 할 일을 완료했을 때 처리하는 기능과 할 일을 삭제하는 기능을 구현하려 한다.
다음과 같이 할 일을 완료하고 사용자가 체크 박스를 클릭하면, 체크된 아이콘으로 바뀌게 되고, todo 내용에 취소선이 생긴다.
TodoId
, index
와 업데이트할 Completed 상태로 false
가 프롭으로 전달된다.TodoId
, index
와 업데이트할 Completed 상태로 true
가 프롭으로 전달된다.completeTodo
를 실행한다import React, { useEffect } from 'react'
import * as m from '../../../../style/MainPagestyle'
import { useSelector, useDispatch } from 'react-redux'
import {BsCircle, BsCheckCircleFill} from 'react-icons/bs'
import {AiOutlineDelete} from 'react-icons/ai'
import { completeTodo, deleteTodo } from '../../../../_redux/todo'
function TodoItem() {
const todos = useSelector(state=>state.Todo.todos);
const dispatch = useDispatch();
const handleComplete = (todoId, index, completed) => {
console.log(todoId, index);
dispatch(completeTodo(todoId, index, completed))
}
return (
<div style={{width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center'}}>
{todos && todos.map((todo,index)=>(
todo.Completed ?
<m.TodoContainer key={index} >
<BsCheckCircleFill className='checkbox' onClick={()=>handleComplete(todo.TodoId, index, false)}/>
<li className='content'style={{ textDecoration: 'line-through' }}>{todo.Content}</li>
</m.TodoContainer>
:
<m.TodoContainer key={index}>
<BsCircle className='checkbox' onClick={()=>handleComplete(todo.TodoId, index, true)}/>
<li className='content' style={{ textDecoration: 'none' }}>{todo.Content}</li>
</m.TodoContainer>
))}
</div>
)
}
export default TodoItem
COMPLETE_TODO
: To-Do 항목의 완료 상태를 업데이트하는 액션을 나타냄completeTodo(todoId, index, completed)
: To-Do 항목의 완료 상태를 업데이트하는 액션 생성자updateCompleted(todoId, completed)
함수를 호출하여 To-Do 항목의 완료 상태를 업데이트하고, COMPLETE_TODO
액션의 페이로드로 인덱스와 업데이트된 완료 상태를 반환COMPLETE_TODO
: 특정 To-Do 항목의 완료 상태를 업데이트import { saveTodo, findallTodo, updateCompleted, deleteItem } from "../firebase/firebase_todo";
//Actions
const COMPLETE_TODO = 'todo_reducer/completetodo'
// Action Creators
export async function completeTodo(todoId, index, completed){
try{
updateCompleted(todoId, completed);
// console.log(todos);
return{
type: COMPLETE_TODO,
payload: {
index: index,
completed: completed
}
}
}catch(error){
console.error("Todo 데이터 업데이트 실패:", error);
throw error;
}
}
//Reducer
const initialState = {
todos:[]
}
export default function (state = initialState, action){
switch (action.type) {
case ADD_TODO:
// 현재 todos 배열에 새로운 todo 데이터 추가
const newTodos = [...state.todos, action.payload];
return { ...state, todos: newTodos };
case INITIALIZE_TODOS:
return {...state, todos: action.payload}
case COMPLETE_TODO:
const index = action.payload.index;
const updatedTodos = [...state.todos];
state.todos[index].Completed = action.payload.completed;
return {...state, todos: updatedTodos}
default:
return state;
}
}
export async function updateCompleted(todoId, completed){
const todo = firestore.collection("todos").doc(todoId);
try{
await todo.update({Completed: completed});
console.log("Document successfully updated!")
}catch(error){
console.log(error);
throw error;
}
}
삭제 버튼을 누르면 해당 todo가 삭제되게 구현하였다.
(...생략...)
function TodoItem() {
const todos = useSelector(state=>state.Todo.todos);
const dispatch = useDispatch();
(...생략...)
const handleDelete = (todoId) =>{
dispatch(deleteTodo(todoId))
}
return (
<div style={{width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center'}}>
{todos && todos.map((todo,index)=>(
todo.Completed ?
<m.TodoContainer key={index} >
<BsCheckCircleFill className='checkbox' onClick={()=>handleComplete(todo.TodoId, index, false)}/>
<li className='content'style={{ textDecoration: 'line-through' }}>{todo.Content}</li>
<AiOutlineDelete className='delete' onClick={()=>handleDelete(todo.TodoId)}/>
</m.TodoContainer>
:
<m.TodoContainer key={index}>
<BsCircle className='checkbox' onClick={()=>handleComplete(todo.TodoId, index, true)}/>
<li className='content' style={{ textDecoration: 'none' }}>{todo.Content}</li>
<AiOutlineDelete className='delete' onClick={()=>handleDelete(todo.TodoId)}/>
</m.TodoContainer>
))}
</div>
)
}
export default TodoItem
DELETE_TODO
: To-Do 항목을 삭제하는 액션을 나타냄deleteTodo(todoId, index)
: To-Do 항목을 삭제하기 위한 액션 생성자deleteItem(todoId)
함수를 호출하여 To-Do 항목을 삭제하고, DELETE_TODO
액션의 페이로드로 삭제된 항목의 ID를 반환합니다.const Todos = state.todos.filter(todo => todo.TodoId !== action.payload);
:filter
함수는 배열의 각 요소를 순회하면서 조건을 만족하는 요소만 남기고 나머지 요소를 제외함import { saveTodo, findallTodo, updateCompleted, deleteItem } from "../firebase/firebase_todo";
//Actions
const DELETE_TODO = 'todo_reducer/deletetodo'
// Action Creators
export async function deleteTodo(todoId, index){
try{
deleteItem(todoId);
// console.log(todos);
return{
type: DELETE_TODO,
payload: todoId
}
}catch(error){
console.error("Todo 데이터 업데이트 실패:", error);
throw error;
}
}
//Reducer
const initialState = {
todos:[]
}
export default function (state = initialState, action){
switch (action.type) {
case ADD_TODO:
// 현재 todos 배열에 새로운 todo 데이터 추가
const newTodos = [...state.todos, action.payload];
return { ...state, todos: newTodos };
case INITIALIZE_TODOS:
return {...state, todos: action.payload}
case COMPLETE_TODO:
const index = action.payload.index;
const updatedTodos = [...state.todos];
state.todos[index].Completed = action.payload.completed;
return {...state, todos: updatedTodos}
case DELETE_TODO:
const Todos = state.todos.filter(todo => todo.TodoId !== action.payload);
return {
...state,
todos: Todos,
};
default:
return state;
}
}