이번에는 지우기 기능을 구현해보겠습니다.
리액트 컴포넌트에서 배열의 불변성을 지키면서 배열 원소를 제거해야 할 경우
배열의 내장함수인 filter를 사용하면 매우 간편합니다.
App.js에 onRemove 함수를 추가해봅시다.
그리고 onInsert와 똑같이 TodoList에 props를 통해 onRemove함수를 전달해주세요.
const onRemove = useCallback(
id => {
setTodos(todos.filter(todo => todo.id !== id));
},
[todos],
);
...
...
<TodoList todos = {todos} onRemove = {onRemove}/>
...
// App.js
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],
);
return (
<div>
<TodoTemplate>
<TodoInsert onInsert={onInsert}/> {/* 생성한 onInsert를 TodoInsert의 props로 설정 */}
<TodoList todos = {todos} onRemove = {onRemove}/>
</TodoTemplate>
</div>
);
}
export default App;
방금과 같은 과정을 거쳐 TodoListItem에서 onRemove를 사용하기 위해서 props를 통해 전달해주세요.
// TodoList.js
import TodoListltem from "./TodoListltem";
import "./TodoList.css";
const TodoList = ({ todos, onRemove }) => {
return (
<section className="TodoList">
{todos.map(item => (
<TodoListltem todo={item} key={item.id} onRemove={onRemove}/>
))}
</section>
);
};
export default TodoList;
// TodoListltem.js
import {
MdCheckBoxOutlineBlank,
MdCheckBox,
MdRemoveCircleOutline
} from "react-icons/md";
import "./TodoListItem.css";
import cn from "classnames";
const TodoListltem = ({ todo, onRemove }) => {
const { id, text, checked } = todo;
return (
<section className='TodoListItem'>
<div className={cn("checkbox", { checked })}>
{checked ?<MdCheckBox/>: <MdCheckBoxOutlineBlank/>}
<div className="text">{text}</div>
</div>
<div className="remove" onClick={() => onRemove(id)}>
<MdRemoveCircleOutline/>
</div>
</section>
);
};
export default TodoListltem;
props를 통해 받아온 todo 배열에 id
를 추가하고 추가한 id를 onRemove의 매개변수로 넣어주세요.
클릭한 항목의 id를 filter를 통해서 id를 제외한 항목만 남김으로써 제거할 수 있습니다.
오른쪽의 빨간 버튼을 누르면 추가한 항목이 삭제되는것을 볼 수 있습니다.