https://ejunyang.tistory.com/entry/PP-%EB%A6%AC%EC%95%A1%ED%8A%B8%EB%A1%9C-ToDoList-%EB%A7%8C%EB%93%A4%EA%B8%B0

 

[P.P] 리액트로 ToDoList 만들기 - UI구현, 리스트 추가

또 다른 프로젝트가 시작됐다 ㅎ 저번주 금요일에 리액트 강의가 발제 됐는데 자바스크립트 보다 훨씬 재밌고, 뭔가 이해가 더 잘 되는것 같다(?) 자바스크립트 라이브러리 아닌가..? 강의 듣는

ejunyang.tistory.com

 

 

 

UI 구현

  • Todo 추가 하기
  • Todo 삭제 하기
  • Todo 완료/취소 상태 변경하기 (진행중 ↔ 완료)

 

기능 구현

  • 제목과 내용을 입력하고, [추가하기] 버튼을 클릭하면 Working에 새로운 Todo가 추가되고 제목 input과 내용 input은 다시 빈 값으로 바뀌도록 구성해주세요.
  • [삭제하기] 버튼을 클릭하면 Working 또는 Done 에 있는 것과 상관없이 삭제처리가 되도록 해주세요.
  • Todo의 isDone 상태가 true이면, 상태 버튼의 라벨을 취소, isDone이 false 이면 라벨을 완료 로 조건부 렌더링 해주세요.
  • Todo의 상태가 Working 이면 위쪽에 위치하고, Done이면 아래쪽에 위치하도록 구현합니다.
  • Layout의 최대 너비는 1200px, 최소 너비는 800px로 제한하고, 전체 화면의 가운데로 정렬해주세요.
  • 컴포넌트 구조는 자유롭게 구현해보세요.

 

 

🍯 HINT

  • 사용한 hook은 오직 useState
  • 기능 구현을 위해 생성한 함수는 2개 입니다. onChangeHandler , onSubmitHandler
  • 사용한 javascript 내장 메서드는 map, filter 입니다.
  • todo의 initial state는 {id: 0, title: “”, body: “”, isDone: false} 입니다.

 


 

컴포넌트

TodoTemplate.jsx  화면을 가운데에 정렬시켜주며, 일정 리스트를 보여줍니다. children으로 내부 JSX를 props로 받아 와서 렌더링해줍니다.
TodoAdd.jsx 할 일을 추가하는 컴포넌트 입니다.
TodoList.jsx todos 배열을 props로 받아 온 후, 이를 배열 내장 함수 map을 사용해서 여러 개의 TodoItem 컴포넌트로 변환하여 보여 줍니다.
TodoItem.jsx 진행중인 할 일 정보를 보여주는 컴포넌트입니다. todo 객체를 props로 받아 와서 상태에 따라 다른 스타일의 UI를 보여줍니다
CurrentDate.jsx 현재 날짜를 알려주는 컴포넌트입니다.
Icons.jsx 배경에 꾸며주는 Sticker 요소를 보여주는 컴포넌트입니다.

 


 

 

 

App.jsx

filter 메서드를 사용해서 배열을 순회하도록 했고, 배열에 있는 id 와 사용자가 선택한 id 가 일치한 값은 삭제가 되고, 일치하지 않는 나머지 값들을 리턴해주도록 했다. 여기서 느슨한 비교와 엄격한 비교를 할 수 있는데 비교 방법은 아래와 같다.

 // 삭제기능
  const onRemove = (id) => {
    setTodo(todos.filter((todo) => todo.id !== id));
  };

 

만들어준 onRemove()는 TodoList 컴포넌트에서 사용할 수 있도록 props 로 내려주자.

return (
    <>
      <TodoTemplate>
        <CurrentDate todos={todos} />
        <TodoList
          key={todos.id}
          todos={todos}
          onRemove={onRemove}
        />
        <TodoAdd onInsert={onInsert} />
      </TodoTemplate>
    </>
  );

 


🐢 느슨한 비교

자체적으로 타입변환이 필요한 경우에만 사용하자.

// 느슨한 비교
console.log(5 == '5'); // true
console.log(0 == false); // true
console.log(null == undefined); // true

 

🔥 엄격한 비교

// 엄격한 비교
console.log(5 === '5'); // false
console.log(0 === false); // false
console.log(null === undefined); // false
 // 느슨한 비교
  const onRemove = (id) => {
    setTodo(todos.filter((todo) => todo.id != id));
  };
  
 // 엄격한 비교
  const onRemove = (id) => {
    setTodo(todos.filter((todo) => todo.id !== id));
  };

 

 

TodoList.jsx

import React from "react";
import TodoItem from "./TodoItem";

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

export default TodoList;

 

TodoItem.jsx

 

내려받은 props 를 고대로 사용만 하면 되는 TodoItem에서 마지막 작업을 해주면 된다. 버튼을 클릭할 때 함수가 실행되도록 해주면 삭제하기 버튼 완료이다. 나는 버튼 모양 대신에 내가 만든 휴지통 아이콘을 넣고싶어서 따로 import해주고 사용봤다.

import React from "react";
import deleteIcon from "../assets/delete.png";
import { IoCheckmark } from "react-icons/io5";
import { PiCircleLight } from "react-icons/pi";

const TodoItem = ({ todo, onRemove }) => {
  const { id, contents, isDone } = todo;
  return (
    <>
      <div className="todoItem">
        <p className="content">{contents}</p>
        <button onClick={() => onRemove(id)}>
          <img src={deleteIcon} />
        </button>
      </div>
    </>
  );
};

export default TodoItem;

 

삭제하기 버튼 생성 완료.. 후후... 기능 구현도 아주 잘 된다.. 후후..

 

+ Recent posts