Project/Todolist

[Header,ToDoList,App]_필터적용

ecoEarth 2022. 12. 20. 22:34

App.js

import { useState } from 'react';
import './App.css';
import Header from './components/Header/Header';
import TodoList from './components/TodoList/TodoList';

const filters = ['all', 'active', 'completed'];
function App() {
  const [filter, setFilter] = useState(filters[0]);
  return (
    <>
      <Header filters={filters} filter={filter} onFilterChange={setFilter} />
      <TodoList filter={filter} />
    </>
  );
}

export default App;

 

아래의 두 코드는 같은 코드이다.

<Header filters={filters} filter={filter} onFilterChange={setFilter} />
<Header filters={filters} filter={filter} onFilterChange={(filter) => setFilter(filter)} />

Header.jsx

import React from 'react';

export default function Header({ filters, filter, onFilterChange }) {
  return (
    <header>
      <ul>
        {filters.map((value, index) => (
          <li key={index}>
            <button onClick={() => onFilterChange(value)}>{value}</button>
          </li>
        ))}
      </ul>
    </header>
  );
}
  • "filters.map((value, index)" 와 같이 filters의 요소중 배열이라면 value와 index만 가져오는 것이 가능하다.

 

Q.여기 써있는 filters.map의 인자 value, index는 개발자의 임의인자인가, built-in인자인가..?

filters.map((value, index)

 

map은 callback 함수를 각각의 요소에 대해 한번씩 순서대로 불러 그 함수의 반환값으로 새로운 배열을 만듭니다. callback 함수는 (undefined도 포함해서) 배열 값이 들어있는 인덱스에 대해서만 호출됩니다. 즉, 값이 삭제되거나 아직 값이 할당/정의되지 않은 인덱스에 대해서는 호출되지 않습니다.callback 함수는 호출될 때 대상 요소의 값, 그 요소의 인덱스, 그리고 map을 호출한 원본 배열 3개의 인수를 전달받습니다. 
from MDN

핵심이 되는 문장은 "callback 함수는 호출될 때 대상 요소의 값, 그 요소의 인덱스, 그리고 map을 호출한 원본 배열 3개의 인수를 전달받습니다."이다. 즉, 저 자리에 value와 index를 써줘서 배열의 value와 index를 가져온 것이 아니라, 원래 저 자리에 무엇을 써주든 value와 index 그리고 원본 배열이 받아져 온다. 

const filters = ["all", "active", "completed"];
filters.map((value, p, u) => console.log(value, p, u));
// all 0 [ 'all', 'active', 'completed' ]
// active 1 [ 'all', 'active', 'completed' ]
// completed 2 [ 'all', 'active', 'completed' ]

p와 u는 각각 index자리와 원본배열자리에 들어있는 인자이기때문에 저러한 출력값을 받을 수 있는 것이다.


ToDoList.jsx

import React, { useState } from "react";
import AddTodo from "../AddtTodo/AddTodo";
import Todo from "../Todo/Todo";
import { v4 as uuidv4 } from "uuid";

export default function TodoList({ filter }) {
  const [todos, setTodos] = useState(initialState);
  const handleAdd = (todo) => setTodos([...todos, todo]);
  const handleUpdate = (updated) =>
    setTodos(todos.map((t) => (t.id === updated.id ? updated : t)));
  const handleDelete = (deleted) =>
    setTodos(todos.filter((t) => t.id !== deleted.id));

  const filtered = getFilteredItems(todos, filter);
  return (
    <section>
      <ul>
        {filtered.map((item) => (
          <Todo
            key={item.id}
            todo={item}
            onUpdate={handleUpdate}
            onDelete={handleDelete}
          />
        ))}
      </ul>
      <AddTodo onAdd={handleAdd} />
    </section>
  );
}

function getFilteredItems(todos, filter) {
  if (filter === "all") {
    return todos;
  }
  return todos.filter((todo) => todo.status === filter);
}

const initialState = [
  { id: uuidv4(), text: "장보기", status: "active" },
  { id: uuidv4(), text: "공부하기", status: "active" },
];