본문 바로가기
팀프로젝트_기록일지/React_이정환_useState,useRef

(8).이정환_react.js강의_App컴포넌트의 items 객체의 배열을 List컴포넌트에 전달하여, 태그형태로 렌더링=>map()렌더링 , 검색기능

by 코잼민 2025. 1. 16.

지난번까지 완성 코드 :

- App.js

import { useRef, useState } from "react";
import "./Editor.css";

function Editor({ onCreateItem }) {
  const [text, setText] = useState("");
  const inputRef = useRef();
  const onChangeInput = (event) => {
    setText(event.target.value);
  };

  const onClickBtn = () => {
    if (text === "") {
      inputRef.current.focus();
      return; //■순서1
    }

    onCreateItem(text);
    setText("");
  };

  const onKeyDownInput = (event) => {
    if (event.keyCode === 13) {
      onClickBtn();
    }
  };

  return (
    <div className="Editor">
      <input
        ref={inputRef}
        value={text}
        onKeyDown={onKeyDownInput}
        onChange={onChangeInput}
        placeholder="새로운 Todo..."
      />
      <button onClick={onClickBtn}>추가</button>
    </div>
  );
}

export default Editor;

- Editor.js

import { useRef, useState } from "react";
import "./Editor.css";

function Editor({ onCreateItem }) {
  const [text, setText] = useState("");
  const inputRef = useRef();
  const onChangeInput = (event) => {
    setText(event.target.value);
  };

  const onClickBtn = () => {
    if (text === "") {
      inputRef.current.focus();
      return; //■순서1
    }

    onCreateItem(text);
    setText("");
  };

  const onKeyDownInput = (event) => {
    if (event.keyCode === 13) {
      onClickBtn();
    }
  };

  return (
    <div className="Editor">
      <input
        ref={inputRef}
        value={text}
        onKeyDown={onKeyDownInput}
        onChange={onChangeInput}
        placeholder="새로운 Todo..."
      />
      <button onClick={onClickBtn}>추가</button>
    </div>
  );
}

export default Editor;

1_ App 컴포넌트의 items를 List 컴포넌트에 전달하기

  • 순서1_ App 컴포넌트 => List 컴포넌트 로 items 를 props로 전달
- App.js
function App() {
  const [items, setItem] = useState(mockData);
  const idRef = useRef(mockData.length); //id 식별을 위한, id에 대한 useRef() 객체 초기화

  const onCreateItem = (context) => {
    const newTodo = {
      id: ++idRef.current, //새로운 item에 id 부여 후, id 증감
      isDone: false,
      content: context,
      date: new Date().getTime(),
    };

    setItem([newTodo, ...items]);
  };

  return (
    <div className="App">
      <Header />
      <Editor onCreateItem={onCreateItem} />
      <List items={items} />//items를 List 컴포넌트에 전달
    </div>
  );
}
  • 순서2_ List 컴포넌트에서 배열의 map() 메소드를 이용해, 모든 배열의 원소를 렌더링
■ key 설정
- List.js
import "./List.css";
import Todoitem from "./Todoitem";
function List({ items }) {
  return (
    <div className="List">
      <p className="List-title">Todo List🌱</p>
      <input placeholder="검색어를 입력하시오." />
      <div className="List-contents">
      {items.map((item)=>{
          return <Todoitem key={item.id} item = {item} />;
        //각 item을 Todoitem 컴포넌트의 key 설정, 각 data인 item 저날
      })}
      </div>
    </div>
  );
}

export default List;
<TodoItem>컴포넌트에 각 배열의 객체 전달
  • 순서3_ <TodoItem>컴포넌트에 각 item의 프로퍼티값 적절하게 배치 출력
- Todoitem.js
import "./Todoitem.css";

function Todoitem({ item }) {//받은 data
  const { isDone, content, date } = item; //변수로 프로퍼티들 추출 하는 법
  return (
  //적절하게 뽑은 프로퍼티값들을 출력
    <div className="TodoItem">
      <input type="checkbox" checked={isDone} />//checkbox일때, 값 대입 방법 기억해놓자
      <p className="TodoItem-content">{content}</p>
      <p className="TodoItem-date">{date}</p>
      <button>삭제</button>
    </div>
  );
}

export default Todoitem;

- 출력 결과 :

&참고 :
{
    id: 1,
    isDone: true,
    content: "빨래하기",
    date: new Date().toISOString().split("T")[0],//date를 날짜 형식 출력 법임
  },

2_ List에 검색 기능 구현해보기

-순서1_ search를 useState 변수 선언 , 검색 input에 입력된 값을 onChange 핸들러 구현, 등록

-순서2_ 업데이트 된 search값에 따라 items배열을 필터링 하는 메소드 구현 :

■ Search가 ""일 경우, => 그냥 모든 items 반환
■ 아니라면, filter(()=>{}) 메소드 이용 , include()메소드 이용하여, 해당되는 item들만 들어있는 items로 반환
■ ★filter((item)=>{}) 사용법 :
items.filter((item)=>{item.검색대상속성.includes(포함 검사 입력값)});
//s붙여야함
■ ▲ 한글이 있기에 => item의 content , 검색 대상 문자열 search 둘다 toLowerCase()로 모두 통일 해야한다.

itemsFilter()메소드 구현부


const itemsFilter = ()=>{
    if(search==="") return items;

    return items,filter((item)=>{item.content.include(search)});
}

-순서3_ itemsFilter()의 반환 값은 filter 후의 items이므로, 변수에 저장 후, map() 렌더링 부분에 반영

const filterItems = itemsFilter();

.
.
.

 return (
    <div className="List">
      <p className="List-title">Todo List🌱</p>
      <input value={search} placeholder="검색어를 입력하시오." />
      <div className="List-contents">
        {filterItems.map((item) => {//items를 filterItems로 코드 수정
          return <Todoitem key={item.id} item={item} />;
        })}
      </div>
    </div>
  );

★ 응용_ 검색창에 입력 후, Enter 입력 시에만, items Filter 되도록 하는 코드 작성

List 컴포넌트

import { useState } from "react";
import "./List.css";
import Todoitem from "./Todoitem";

function List({ items }) {
  const [search, setSearch] = useState(""); // 검색창 입력 상태
  const [filterQuery, setFilterQuery] = useState(""); // 실제 필터링에 사용하는 상태

  // 검색창 입력 시 호출
  const onChangeSearch = (event) => {
    setSearch(event.target.value);
  };

  // Enter 키 입력 시 호출
  const onKeyDownSearch = (event) => {
    if (event.key === "Enter") {
      setFilterQuery(search); // filterQuery를 업데이트
    }
  };

  // 필터링된 항목 계산
  const getFilteredItems = () => {
    if (filterQuery === "") return items; // 검색어가 없으면 전체 반환
    return items.filter((item) =>
      item.content.toLowerCase().includes(filterQuery.toLowerCase())
    );
  };

  const filteredItems = getFilteredItems();

  return (
    <div className="List">
      <p className="List-title">Todo List🌱</p>
      <input
        placeholder="검색어를 입력하시오."
        onChange={onChangeSearch} // 검색창 입력
        onKeyDown={onKeyDownSearch} // Enter 키 입력
        value={search} // 입력 상태 연결
      />
      <div className="List-contents">
        {filteredItems.map((item) => (
          <Todoitem key={item.id} item={item} />
        ))}
      </div>
    </div>
  );
}

export default List;

 

- 출력 결과 :