블로그를 이전하였습니다. 2023년 11월부터 https://bluemiv.github.io/에서 블로그를 운영하려고 합니다. 앞으로 해당 블로그의 댓글은 읽지 못할 수 도 있으니 양해바랍니다.
반응형
완료 목록 조회 기능 개발
이전 글에서는 '할 일' 목록 조회 기능을 개발했지만, 이번엔 완료 목록 조회 기능을 개발한다.
할 일과 완료한 일을 구분하기 위해 checked
라는 플래그(Flag) 값이 필요하다.
true
: 완료한 일false
: 아직 완료하지 않은 일
체크박스 체크 또는 체크 해제 기능
우선, 체크 박스를 체크 했을때, checked의 값이 바뀌도록 해보자
InputBox.jsx
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로 하여, 완료하지 않은 항목으로 설정한다.
ToDoItem.jsx
checkbox를 클릭하면, todoItem의 checked 값이 toggle 되도록한다.
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 시킨다.
할 일 목록과 완료한 목록 나누기
Home.jsx
checkedList로 ToDoItemList 컴포넌트에서 '할 일 목록'을 보여줄건지 '완료한 목록'을 보여줄건지 설정한다.
false
: 체크가 안됨 -> 해야할 할 일true
: 체크 됨 -> 완료한 일
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;
ToDoItemList.jsx
props로 checkedList를 받아와서 todoItem.checked와 동일한 아이템만 출력한다.
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 하면 된다.
완료한 아이템 스타일 입히기
완료한 일은 색상과 폰트 스타일, 취소선을 넣어서 완료한 느낌(?)이 풍기도록 스타일을 입힌다.
완료한 일은 수정할 수 없도록 기획했으므로, 완료한 일의 경우엔 수정 버튼이 보이지 않도록 한다.
ToDoItem.jsx
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;
App.css
이탤릭체로 기울이고, 취소선을 넣는다. 색상은 회색으로 설정한다.
.todoapp__item-ctx-checked {
font-style: italic;
text-decoration: line-through;
color: #868e96;
}
결과 화면 확인
전체 코드는 아래 링크에서 확인 할 수 있습니다.
https://github.com/bluemiv/react_todo_app
반응형
'Frontend > React' 카테고리의 다른 글
React로 간단한 ToDo List 만들기 (#8 삭제 기능 개발) (0) | 2021.07.17 |
---|---|
React로 간단한 ToDo List 만들기 (#7 수정 기능 개발) (0) | 2021.07.16 |
React로 간단한 ToDo List 만들기 (#5 할 일 목록 조회 기능 개발) (0) | 2021.07.13 |
React로 간단한 ToDo List 만들기 (#4 Item 추가 기능 개발) (0) | 2021.07.13 |
React로 간단한 ToDo List 만들기 (#3 전체적인 틀 개발) (0) | 2021.07.12 |