본문 바로가기

카테고리 없음

[React] React로 할 일 관리 앱 만들기: 5장 - 필터링과 통계

반응형

 

 

안녕하세요! 이번 포스트에서는 우리의 할 일 관리 앱에 할 일 필터링 기능과 통계를 표시하는 기능을 추가해 보겠습니다.

1. 할 일 필터링 기능 구현

먼저 TodoList 컴포넌트에 필터링 기능을 추가해 보겠습니다.

import React, { useState, useEffect } from 'react';

function TodoList() {
  const [todos, setTodos] = useState(() => {
    const savedTodos = localStorage.getItem('todos');
    return savedTodos ? JSON.parse(savedTodos) : [];
  });
  const [inputValue, setInputValue] = useState('');
  const [editingId, setEditingId] = useState(null);
  const [filter, setFilter] = useState('all');

  // ... 이전 코드 ...

  const filteredTodos = todos.filter((todo) => {
    if (filter === 'active') {
      return !todo.completed;
    } else if (filter === 'completed') {
      return todo.completed;
    }
    return true;
  });

  return (
    <div>
      <h2>할 일 목록</h2>
      {/* ... 이전 코드 ... */}
      <div>
        <button onClick={() => setFilter('all')}>전체</button>
        <button onClick={() => setFilter('active')}>미완료</button>
        <button onClick={() => setFilter('completed')}>완료</button>
      </div>
      <ul>
        {filteredTodos.map((todo) => (
          // ... 이전 코드 ...
        ))}
      </ul>
    </div>
  );
}

이 코드에서는:

  • filter 상태를 추가하여 현재 필터 상태를 추적합니다.
  • filteredTodos 변수를 생성하여 현재 필터에 따라 할 일 목록을 필터링합니다.
  • 필터 버튼을 추가하여 사용자가 필터를 변경할 수 있게 합니다.

2. 할 일 통계 표시 기능 구현

이제 할 일 통계를 표시하는 기능을 추가해 보겠습니다.

function TodoList() {
  // ... 이전 코드 ...

  const totalTodos = todos.length;
  const completedTodos = todos.filter((todo) => todo.completed).length;
  const activeTodos = totalTodos - completedTodos;

  return (
    <div>
      <h2>할 일 목록</h2>
      {/* ... 이전 코드 ... */}
      <div>
        <p>전체 할 일: {totalTodos}</p>
        <p>완료한 할 일: {completedTodos}</p>
        <p>남은 할 일: {activeTodos}</p>
      </div>
    </div>
  );
}

이 코드에서는:

  • 전체 할 일, 완료한 할 일, 남은 할 일의 개수를 계산합니다.
  • 계산된 통계를 화면에 표시합니다.

3. 최종 TodoList 컴포넌트

모든 기능을 합친 최종 TodoList 컴포넌트는 다음과 같습니다:

import React, { useState, useEffect } from 'react';

function TodoList() {
  const [todos, setTodos] = useState(() => {
    const savedTodos = localStorage.getItem('todos');
    return savedTodos ? JSON.parse(savedTodos) : [];
  });
  const [inputValue, setInputValue] = useState('');
  const [editingId, setEditingId] = useState(null);
  const [filter, setFilter] = useState('all');

  useEffect(() => {
    localStorage.setItem('todos', JSON.stringify(todos));
  }, [todos]);

  const handleInputChange = (e) => {
    setInputValue(e.target.value);
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    if (inputValue.trim() !== '') {
      setTodos([...todos, { id: Date.now(), text: inputValue, completed: false }]);
      setInputValue('');
    }
  };

  const handleDelete = (id) => {
    setTodos(todos.filter((todo) => todo.id !== id));
  };

  const handleToggle = (id) => {
    setTodos(
      todos.map((todo) =>
        todo.id === id ? { ...todo, completed: !todo.completed } : todo
      )
    );
  };

  const handleEdit = (id, newText) => {
    setTodos(
      todos.map((todo) =>
        todo.id === id ? { ...todo, text: newText } : todo
      )
    );
    setEditingId(null);
  };

  const filteredTodos = todos.filter((todo) => {
    if (filter === 'active') {
      return !todo.completed;
    } else if (filter === 'completed') {
      return todo.completed;
    }
    return true;
  });

  const totalTodos = todos.length;
  const completedTodos = todos.filter((todo) => todo.completed).length;
  const activeTodos = totalTodos - completedTodos;

  return (
    <div>
      <h2>할 일 목록</h2>
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          value={inputValue}
          onChange={handleInputChange}
          placeholder="새로운 할 일을 입력하세요"
        />
        <button type="submit">추가</button>
      </form>
      <div>
        <button onClick={() => setFilter('all')}>전체</button>
        <button onClick={() => setFilter('active')}>미완료</button>
        <button onClick={() => setFilter('completed')}>완료</button>
      </div>
      <ul>
        {filteredTodos.map((todo) => (
          <li key={todo.id}>
            <input
              type="checkbox"
              checked={todo.completed}
              onChange={() => handleToggle(todo.id)}
            />
            {editingId === todo.id ? (
              <input
                type="text"
                value={todo.text}
                onChange={(e) => handleEdit(todo.id, e.target.value)}
                onBlur={() => setEditingId(null)}
                autoFocus
              />
            ) : (
              <span
                style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}
                onDoubleClick={() => setEditingId(todo.id)}
              >
                {todo.text}
              </span>
            )}
            <button onClick={() => handleDelete(todo.id)}>삭제</button>
          </li>
        ))}
      </ul>
      <div>
        <p>전체 할 일: {totalTodos}</p>
        <p>완료한 할 일: {completedTodos}</p>
        <p>남은 할 일: {activeTodos}</p>
      </div>
    </div>
  );
}

export default TodoList;

실행 결과

이제 npm start 명령어로 앱을 실행하면, 할 일을 필터링할 수 있고 할 일 통계를 볼 수 있습니다.

다음 단계

이번 챕터에서는 할 일 필터링 기능과 통계 표시 기능을 구현했습니다. 이로써 기본적인 할 일 관리 앱의 기능을 모두 구현했습니다. 다음 챕터에서는 앱의 디자인을 개선하고, 컴포넌트를 더 작은 단위로 분리하여 코드의 가독성과 유지보수성을 높이는 방법에 대해 알아보겠습니다.

반응형