본문 바로가기

리액트 React/투두앱 만들기

투두앱 만들기 5: 투두 수정하기

반응형

수정하기 구현은 전편 삭제하기와 비슷합니다. 내장함수 map을 이용하여 onToggle함수를 작성하고 App->TodoList->TodoListItem순으로 전달해줍니다. 

 

onToggle 
import React, { useState, useRef, useCallback } from "react";
import TodoInsert from "./components/TodoInsert/TodoInsert";
import TodoList from "./components/TodoList/TodoList";
import TodoTemplate from "./components/TodoTemplate/TodoTemplate";

const App = () => {
  const [todos, setTodos] = useState([]);

  const nextId = useRef(0);

  const onInsert = useCallback(
    (text) => {
      const todo = { id: nextId.current, text, checked: false };
      setTodos(todos.concat(todo));
      nextId.current += 1;
    },
    [todos]
  );

  const onRemove = useCallback(
    (id) => {
      setTodos(todos.filter((todo) => todo.id !== id));
    },
    [todos]
  );

  const onToggle = useCallback(
    (id) => {
      setTodos(
        todos.map((todo) =>
          todo.id === id ? { ...todo, checked: !todo.checked } : todo
        )
      );
    },
    [todos]
  );

  return (
    <TodoTemplate>
      <TodoInsert onInsert={onInsert} />
      <TodoList todos={todos} onRemove={onRemove} onToggle={onToggle} />
    </TodoTemplate>
  );
};

export default App;

map을 이용하여 todos안에 투두객체중 특정 id값을 가지고 있는 투두의 checked값을 반전시켜줍니다. 파라미터로 사용된 id값이 todo.id와 같을경우 새로운 객체를 생성, 다를경우 처음 상태 그대로 반환합니다. (todo.id===id ? .. : .. ). 즉, todos배열에서 변화가 필요한 원소만 업데이트되고 나머지는 그대로 남게됩니다(새로운 배열 생성X). 

 

TodoList.js

import React from "react";
import TodoListItem from "../TodoListItem/TodoListItem";
import { ToDoList } from "./TodoList.styles";

const TodoList = ({ todos, onRemove, onToggle }) => {
  return (
    <ToDoList>
      {todos.map((todo) => (
        <TodoListItem todo={todo} key={todo.id} onRemove={onRemove} onToggle={onToggle} />
      ))}
    </ToDoList>
  );
};

export default TodoList;

App에서 받은 onToggle을 그대로 TodoListItem에 전달합니다.

 

TodoListItem.js

import React from "react";
import {
  MdCheckBox,
  MdCheckBoxOutlineBlank,
  MdRemoveCircleOutline,
} from "react-icons/md";
import "./TodoListItem.styles";
import {
  CheckBox,
  Remove,
  ToDoListItem,
  ToDoText,
} from "./TodoListItem.styles";

const TodoListItem = ({ todo, onRemove, onToggle }) => {
  const { id, text, checked } = todo;

  return (
    <ToDoListItem>
      <CheckBox onClick={() => onToggle(id)} checked={checked}>
        {checked ? <MdCheckBox /> : <MdCheckBoxOutlineBlank />}
        <ToDoText>{text}</ToDoText>
      </CheckBox>
      <Remove onClick={() => onRemove(id)}>
        <MdRemoveCircleOutline />
      </Remove>
    </ToDoListItem>
  );
};

export default TodoListItem;

TodoListItem.styles.js

(...)

export const CheckBox = styled.div`
  cursor: pointer;
  flex: 1;
  display: flex;
  align-items: center;
  svg {
    font-size: 1.5rem;
  }
  ${(props) =>
    props.checked &&
    css`
      color: #adb5bd;
      text-decoration: line-through;
      svg{
        color: #22b8cf};

    }
  `}
`;


(...)

checked값을 props으로 받아와 스타일을 완성시켜 줍니다. 

 

$ yarn start

반응형