본문 바로가기
JavaScript/React

React) 일정 관리 웹 애플리케이션 만들기 - 2 (항목 지우기, 수정하기 기능 구현)

by 박채니 2022. 11. 20.
안녕하세요, 코린이의 코딩 학습기 채니 입니다.
[리액트를 다루는 기술]의 책을 참고하여 포스팅한 개인 공부 내용입니다.

 

* 이전 포스팅 참고

https://chanychu.tistory.com/451

 

React) 일정 관리 웹 애플리케이션 만들기 - 2 (todoList 렌더링, 항목 추가 기능 구현하기)

안녕하세요, 코린이의 코딩 학습기 채니 입니다. [리액트를 다루는 기술]의 책을 참고하여 포스팅한 개인 공부 내용입니다. * 프로젝트 준비 및 UI 구성은 아래 포스트 참고 https://chanychu.tistory.com/

chanychu.tistory.com

 

지우기 기능 구현하기

 

배열 내장 함수 filter

 

배열의 불변성을 지키면서 배열 원소를 제거해야하는 경우, filter 함수를 사용하면 간단히 처리할 수 있습니다.

특정 조건을 만족하는 원소들만 따로 추출하여 새로운 배열을 만들어주기 때문입니다.

 

사용 예시

const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const biggerThanFive = array.filter(number => number > 5);

// 결과 : [6, 7, 8, 9, 10]

조건을 확인해주는 함수를 파라미터로 넣어주고, true 혹은 false를 반환해야 합니다.

true를 반환하는 경우에만 배열에 포함됩니다.

 

todos 배열에서 id로 항목 지우기

 

App 컴포넌트에서 id를 파라미터로 받아와 같은 id를 가진 항목을 todos 배열에서 지우겠습니다.

 

App.js

	... 
	...

  const onRemove = useCallback(id => {
    setTodos(todos.filter(todo => todo.id !== id));
  }, [todos]);

  return (
    <TodoTemplate>
      <TodoInsert onInsert={onInsert}/>
      <TodoList todos={todos} onRemove={onRemove} />
    </TodoTemplate>
  )
}

export default App;

useCallback을 이용해 함수를 재사용하도록 하였으며, id를 파라미터로 받아 filter를 이용해 각 todo의 id가 넘어온 id값과 같지 않은 todo들만 추려서 새로운 배열을 다시 set해주었습니다.

해당 함수는 TodoListItem에서 사용해야 하므로, TodoList의 props로 설정해주었습니다.

 

TodoListItem에서 삭제 함수 호출하기

 

TodoList.js

import './TodoList.scss';
import TodoListItem from './TodoListItem';

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

export default TodoList;

TodoList에서 props로 받아온 onRemove함수를 다시 TodoListItem의 props로 전달해주었습니다.

 

TodoListItem.js

import cn from 'classnames'
import { MdCheckBox, MdRemoveCircleOutline, MdCheckBoxOutlineBlank } from 'react-icons/md';
import './TodoListItem.scss';

const TodoListItem = ({ todo, onRemove }) => {
    const { id, text, checked } = todo;

    return (
        <div className='TodoListItem'>
            <div className={cn('checkbox', { checked })}>
                {checked ? <MdCheckBox /> : <MdCheckBoxOutlineBlank />}
                <div className='text'>{text}</div>
            </div>
            <div className='remove' onClick={() => onRemove(id)}>
                <MdRemoveCircleOutline />
            </div>
        </div>
    );
}

export default TodoListItem;

TodoList에서 props로 받은 onRemove를 삭제 아이콘 클릭 시 실행되도록 하였으며, 이 때 파라미터로 id 값을 넘겨주게 됩니다.

삭제 버튼 클릭 시

삭제처리가 잘 되는 것을 확인할 수 있습니다.

 


수정 기능

 

위에서 구현한 삭제 기능과 비슷한 로직으로 구현해보겠습니다.

 

App.js

    ...
    ...
    
  const onToggle = useCallback(id => {
    setTodos(todos.map(todo => (
      todo.id === id ? { ...todo, checked: !todo.checked } : todo
    )))
  }, [todos]);

  return (
    <TodoTemplate>
      <TodoInsert onInsert={onInsert}/>
      <TodoList todos={todos} onRemove={onRemove} onToggle={onToggle} />
    </TodoTemplate>
  )
}

export default App;

 map을 이용해 선택한 id값을 찾아 checked를 반전시켜주었고, 해당 id값이 아닌 todo들은 삼항 연산자를 이용해 처음 그 상태 그대로를 반환하게 하였습니다.

 

TodoList.js

import './TodoList.scss';
import TodoListItem from './TodoListItem';

const TodoList = ({ todos, onRemove, onToggle }) => {
    return (
        <div className='TodoList'>
            {
                todos.map(todo => (
                    <TodoListItem todo={todo} key={todo.id} onRemove={onRemove} onToggle={onToggle} />
                ))
            }
        </div>
    )
}

export default TodoList;

 

TodoListItem.js

import cn from 'classnames'
import { MdCheckBox, MdRemoveCircleOutline, MdCheckBoxOutlineBlank } from 'react-icons/md';
import './TodoListItem.scss';

const TodoListItem = ({ todo, onRemove, onToggle }) => {
    const { id, text, checked } = todo;

    return (
        <div 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>
        </div>
    );
}

export default TodoListItem;

체크, 체크 해제 모두 잘 실행 되는 것을 확인할 수 있습니다.