memostack
article thumbnail
블로그를 이전하였습니다. 2023년 11월부터 https://bluemiv.github.io/에서 블로그를 운영하려고 합니다. 앞으로 해당 블로그의 댓글은 읽지 못할 수 도 있으니 양해바랍니다.
반응형

1. 완료 목록 조회 기능 개발

이전 글에서는 '할 일' 목록 조회 기능을 개발했지만, 이번엔 완료 목록 조회 기능을 개발한다.

 

할 일과 완료한 일을 구분하기 위해 checked 라는 플래그(Flag) 값이 필요하다.

  • true: 완료한 일
  • false: 아직 완료하지 않은 일

 

1.1. 체크박스 체크 또는 체크 해제 기능

우선, 체크 박스를 체크 했을때, checked의 값이 바뀌도록 해보자

 

1.1.1. InputBox.jsx

<javascript />
import React, { useRef, useState } from 'react'; import PropTypes from 'prop-types'; const InputBox = ({ todoList, setTodoList }) => { const [text, setText] = useState(''); const inputRef = useRef(null); // input 값 가져오기 const onChangeInput = (e) => { setText(e.target.value); }; const onClickAddButton = () => { // todoItemList에 값 추가 const nextTodoList = todoList.concat({ id: todoList.length, text, checked: false, // (1) }); setTodoList(nextTodoList); // input 값 초기화 및 포커싱 setText(''); inputRef.current.focus(); }; return ( <div className="todoapp__inputbox"> {/* 아이템 내용 입력 input */} <input type="text" name="todoItem" value={text} ref={inputRef} placeholder="할 일을 입력해주세요" className="todoapp__inputbox-inp" onChange={onChangeInput} /> {/* 입력 후 아이템 추가 버튼 */} <button type="submit" className="todoapp__inputbox-add-btn" onClick={onClickAddButton} > 추가 </button> </div> ); }; // props 값 검증 InputBox.propTypes = { todoList: PropTypes.arrayOf( PropTypes.shape({ id: PropTypes.number.isRequired, text: PropTypes.string.isRequired, }).isRequired ), setTodoList: PropTypes.func.isRequired, }; export default InputBox;
  • (1): 처음 아이템을 등록할때는 checked의 값을 false로 하여, 완료하지 않은 항목으로 설정한다.

 

1.1.2. ToDoItem.jsx

checkbox를 클릭하면, todoItem의 checked 값이 toggle 되도록한다.

<javascript />
import React from 'react'; import PropTypes from 'prop-types'; const ToDoItem = ({ todoItem, todoList, setTodoList }) => { const onChangeCheckbox = () => { const nextTodoList = todoList.map((item) => ({ ...item, // id 값이 같은 항목의 checked 값을 Toggle 함 checked: item.id === todoItem.id ? !item.checked : item.checked, })); setTodoList(nextTodoList); }; return ( <li className="todoapp__item"> {/* 아이템 완료 체크 / 체크 해제를 위한 체크박스 */} <input type="checkbox" className="todoapp__item-checkbox" checked={todoItem.checked} // (1) onChange={onChangeCheckbox} // (2) /> {/* 아이템 내용 */} <span className="todoapp__item-ctx">{todoItem.text}</span> {/* 수정 버튼 */} <button type="button" className="todoapp__item-edit-btn"></button> {/* 삭제 버튼 */} <button type="button" className="todoapp__item-delete-btn"> 🗑 </button> </li> ); }; ToDoItem.propTypes = { todoItem: PropTypes.shape({ id: PropTypes.number, text: PropTypes.string.isRequired, }), todoList: PropTypes.arrayOf( PropTypes.shape({ id: PropTypes.number.isRequired, text: PropTypes.string.isRequired, }) ), setTodoList: PropTypes.func.isRequired, }; export default ToDoItem;
  • (1): 체크 또는 체크해제를 구분할 수 있도록, input의 checked에 todoItem의 checked를 넣는다.
  • (2): 변화가 생기면 todoItem의 checked 값을 Toggle 시킨다.

 

1.2. 할 일 목록과 완료한 목록 나누기

1.2.1. Home.jsx

checkedList로 ToDoItemList 컴포넌트에서 '할 일 목록'을 보여줄건지 '완료한 목록'을 보여줄건지 설정한다.

  • false: 체크가 안됨 -> 해야할 할 일
  • true: 체크 됨 -> 완료한 일
<javascript />
import React, { useState } from 'react'; import InputBox from '../components/InputBox'; import ToDoItemList from '../components/ToDoItemList'; const Home = () => { const [todoList, setTodoList] = useState([]); return ( <div className="homepage__container"> {/* ToDo Item을 추가할 수 있는 input 박스 */} <InputBox todoList={todoList} setTodoList={setTodoList} /> {/* 할 일 Item 리스트 */} <ToDoItemList title={'할 일'} todoList={todoList} setTodoList={setTodoList} checkedList={false} // (체크되지 않은) 할 일 목록 /> {/* 완료한 Item 리스트 */} <ToDoItemList title={'완료한 항목'} todoList={todoList} setTodoList={setTodoList} checkedList={true} // (체크되어 있는)완료한 목록 /> </div> ); }; export default Home;

 

1.3. ToDoItemList.jsx

props로 checkedList를 받아와서 todoItem.checked와 동일한 아이템만 출력한다.

<javascript />
import React from 'react'; import PropTypes from 'prop-types'; import ToDoItem from './ToDoItem'; const ToDoItemList = ({ title, todoList, setTodoList, checkedList }) => ( <div className="todoapp__list"> {/* props로 부터 title 값을 전달 받음 */} <p className="todoapp__list-tit">{title}</p> <ul className="todoapp__list-ul"> {todoList && // todoList가 있을때만 출력 todoList.map((todoItem) => { // checkedList 값에 따라 '할 일 목록' 또는 '완료한 목록'을 출력 if (checkedList !== todoItem.checked) return null; return ( // map을 이용하여 ToDoItem을 출력 <ToDoItem key={todoItem.id} todoItem={todoItem} todoList={todoList} setTodoList={setTodoList} /> ); })} </ul> </div> ); ToDoItemList.propTypes = { title: PropTypes.string.isRequired, todoList: PropTypes.arrayOf( PropTypes.shape({ id: PropTypes.number.isRequired, text: PropTypes.string.isRequired, }) ), setTodoList: PropTypes.func.isRequired, checkedList: PropTypes.bool.isRequired, }; export default ToDoItemList;
화면에 아무것도 출력하고 싶지 않을때는 null을 return 하면 된다.

 

1.4. 완료한 아이템 스타일 입히기

완료한 일은 색상과 폰트 스타일, 취소선을 넣어서 완료한 느낌(?)이 풍기도록 스타일을 입힌다.

완료한 일은 수정할 수 없도록 기획했으므로, 완료한 일의 경우엔 수정 버튼이 보이지 않도록 한다.

 

1.4.1. ToDoItem.jsx

<javascript />
import React from 'react'; import PropTypes from 'prop-types'; const ToDoItem = ({ todoItem, todoList, setTodoList }) => { const onChangeCheckbox = () => { const nextTodoList = todoList.map((item) => ({ ...item, // id 값이 같은 항목의 checked 값을 Toggle 함 checked: item.id === todoItem.id ? !item.checked : item.checked, })); setTodoList(nextTodoList); }; return ( <li className="todoapp__item"> {/* 아이템 완료 체크 / 체크 해제를 위한 체크박스 */} <input type="checkbox" className="todoapp__item-checkbox" checked={todoItem.checked} onChange={onChangeCheckbox} /> {/* 아이템 내용 */} <span className={`todoapp__item-ctx ${ todoItem.checked ? 'todoapp__item-ctx-checked' : '' }`} > {todoItem.text} </span> { // 수정 버튼 // 완료한 일인 경우에는 null을 반환하여 보이지 않도록 함 !todoItem.checked ? ( <button type="button" className="todoapp__item-edit-btn"></button> ) : null } {/* 삭제 버튼 */} <button type="button" className="todoapp__item-delete-btn"> 🗑 </button> </li> ); }; ToDoItem.propTypes = { todoItem: PropTypes.shape({ id: PropTypes.number, text: PropTypes.string.isRequired, }), todoList: PropTypes.arrayOf( PropTypes.shape({ id: PropTypes.number.isRequired, text: PropTypes.string.isRequired, }) ), setTodoList: PropTypes.func.isRequired, }; export default ToDoItem;

 

1.5. App.css

이탤릭체로 기울이고, 취소선을 넣는다. 색상은 회색으로 설정한다.

<css />
.todoapp__item-ctx-checked { font-style: italic; text-decoration: line-through; color: #868e96; }

 

2. 결과 화면 확인

결과 화면

 

전체 코드는 아래 링크에서 확인 할 수 있습니다.

https://github.com/bluemiv/react_todo_app

 

GitHub - bluemiv/react_todo_app: React로 만든 ToDo Web Application

React로 만든 ToDo Web Application. Contribute to bluemiv/react_todo_app development by creating an account on GitHub.

github.com

 
반응형
블로그를 이전하였습니다. 2023년 11월부터 https://bluemiv.github.io/에서 블로그를 운영하려고 합니다. 앞으로 해당 블로그의 댓글은 읽지 못할 수 도 있으니 양해바랍니다.
profile

memostack

@bluemiv_mm

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!