체크박스를 통해 항목을 체크하는 기능을 구현해 보겠습니다.
이것 또한 onRewrite함수를 App.js에 만들고 TodoList를 통해 TodoListItem에 전달해주세요
// 항목 토글 기능 구현
const onToggle = useCallback(
id => {
setTodos(
todos.map(todo => todo.id === id? {...todo, checked: !todo.checked} : todo)
);
},
[todos],
);
이 함수는 항목의 id를 파라미터로 받아, 해당 항목의 checked 속성을 반대로 변경합니다.
todo.id === id
현재 반복문(map함수)을 돌며 처리 중인 todo 항목의 id와 함수에 전달된 id(즉, 클릭하여 토글하려는 todo 항목의 id)가 같은지를 비교하는 조건문입니다. 같다면 true를, 아니라면 false를 반환합니다.
{ ...todo, checked: !todo.checked }
이 부분은 JavaScript의 스프레드 연산자와 객체 리터럴을 사용하여, 기존의 todo 객체에 대한 새로운 복사본을 만들고, 그 복사본의 checked 속성 값을 반전시킨 새로운 객체를 생성합니다. { ...todo }는 todo 객체의 모든 속성을 새 객체에 복사하고, checked: !todo.checked는 복사본의 checked 속성 값을 기존 값의 반대로 설정합니다. 결과적으로, 이 코드는 todo 항목의 체크 상태를 토글한 새로운 객체를 반환합니다.
todo가 반환되는 경우는 todo.id === id의 결과가 false일 때입니다. 즉, 현재 반복문을 돌며 처리 중인 todo 항목의 id가 함수에 전달된 id와 다른 경우입니다. 이 경우는 토글하려는 항목이 아니므로, todo 항목을 그대로 반환합니다.
import './reset.css';
import { useState, useCallback, useRef } from 'react';
import TodoInsert from "./components/TodoInsert";
import TodoTemplate from "./components/TodoTemplate";
import TodoList from './components/TodoList';
function App() {
const [todos, setTodos] = useState([
{
id: 1,
text: "리액트 기초 알아보기",
checked: true,
},
{
id: 2,
text: "컴포넌트 스타일링해 보기",
checked: true,
},
{
id: 3,
text: "일정관리 앱 시작하기",
checked: false,
},
]);
/// 고유값으로 사용할 id => ref를 사용하여 변수 담기
const nextId = useRef(4);
// 항목을 추가할 onIsert 함수 생성
const onInsert = useCallback(text => {
const todo = {
id: nextId.current,
text,
checked: false,
};
setTodos(todos.concat(todo));
nextId.current += 1; // nextId 1씩 더하기
},
[todos]
);// 의존성 배열 ▼
// todos가 변경될 때마다 새로운 함수가 생성됩니다.
// 따라서, onInsert 함수는 항상 최신의 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 (
<div>
<TodoTemplate>
<TodoInsert onInsert={onInsert}/> {
/* 생성한 onInsert를 TodoInsert의 props로 설정 */}
<TodoList todos = {todos} onRemove = {onRemove} onToggle={onToggle}/>
</TodoTemplate>
</div>
);
}
export default App;
import TodoListltem from "./TodoListltem";
import "./TodoList.css";
const TodoList = ({ todos, onRemove, onToggle }) => {
return (
<section className="TodoList">
{todos.map(item => (
<TodoListltem
todo={item}
key={item.id}
onRemove={onRemove}
onToggle={onToggle}
/>
))}
</section>
);
};
export default TodoList;
import {
MdCheckBoxOutlineBlank,
MdCheckBox,
MdRemoveCircleOutline
} from "react-icons/md";
import "./TodoListItem.css";
import cn from "classnames";
const TodoListltem = ({ todo, onRemove, onToggle }) => {
const { id, text, checked } = todo;
return (
<section className='TodoListItem'>
<div className={cn("checkbox", { checked })} onClick={() => onToggle(id)}>
{checked ?<MdCheckBox/>: <MdCheckBoxOutlineBlank/>}
<div className="text">{text}</div>
</div>
<div className="remove" onClick={() => onRemove(id)}>
<MdRemoveCircleOutline/>
</div>
</section>
);
};
export default TodoListltem;