#20.TIL | React(Componet재사용, filter를 활용한 검색기능)

Seongjae Hwang·2021년 11월 27일
1

Component 재사용

인스타그램 클론코딩을 진행해보면서 하나의 피드 Component를 만들었던 것을 가지고 데이터를 통해 map을 활용하여 여러개의 피드를 찍은것을 보며 React의 장점을 다시금 알게 되었다. 오늘은 Monsters라는 과제를 하면서 Component재사용과 Props의 활용등을 다시 공부하게 되었다.

데이터의 흐름

Monsters.js > CardList.js > Card.js

1. Monsters.js에서 먼저 fetch함수를 통해 데이터를 전달받고, 이를 json형태로 전환한뒤, State에 저장.


그러면 이러한 형태의 데이터가 State에 담기게 되고, 이 데이터를 활용하여 컴포넌트 UI들을 화면에 보여줘야 되니 이를 Props로 전달해주었다.

2. CardList.js에 데이터 State를 Props로 전달하여 map사용.

CardList에서는 전달받은 데이터의 개수만큼, 위에 사진에서는 총 10개의 데이터를 전달받았으니 10번의 map을 돌아 총 10개의 UI를 찍을 수 있게 된다.

3. Card.js한테 Props로 데이터의 id, name, email을 전달.

function Card(props) {
  return (
    <div className="card-container">
      <img
        src={`https://robohash.org/${props.id}?set=set2&size=180x180`}
        alt="monster"
      />
      <h2>{props.name}</h2>
      <p>{props.email}</p>
    </div>
  );
}

따라서, 이 한개의 Component를 만듦으로써 각각의 사진, 이름, email정보를 가진 UI들을 데이터의 개수만큼 찍어낼 수 있다.

filter를 활용한 검색기능

그렇다면 이러한 방식으로 찍어낸 UI들을 검색하고 싶다면 어떻게 해야될까. 처음에는 input에 onChange를 사용하여 e.target.value를 state를 담고 이를 활용하여 filter를 사용하면 되겠다라고 생각했었는데, 생각해보니 보통 검색창에서는 입력값에 실시간으로 UI가 그려지는 것이 아닌 검색버튼을 눌렀을때 실행이 되니 onClick이벤트과 state를 적절히 잘 활용해야겠다는 생각이 들었다.

1. State 두개를 사용하여 Props로 전달할 input값 다루기

function Monsters() {

  const [monsters, setMonsters] = useState([]);

  const [search, setSearch] = useState("");
  const [callbackSearch, setcallbackSearch] = useState("");
  
  useEffect(() => {
    fetch(`https://jsonplaceholder.typicode.com/users`)
      .then((response) => response.json())
      .then((json) => setMonsters(json));
  }, []);


  return (
    <div className="monsters">
      <h1>컴포넌트 재사용 연습!</h1>
    
      <input
        value={search}
        placeholder="몬스터찾기"
        type="text"
        onChange={(e) => {
          setSearch(e.target.value);
        }}
      />

      <button
        onClick={() => {
          setcallbackSearch(search);
        }}
      > 검색
      </button>

      <CardList monsters={monsters} search={callbackSearch} />
    </div>
  );
}

우선 filter를 사용하려면 input창에서 일어나는 value를 알아야 하니, search라는 state에서 실시간으로 입력되는 e.target.value를 담아주었다.
처음에는 실시간으로 input의 value를 담은 search state를 바로 CardList.js에게 Props로 전달해주려고 했지만, 실시간으로 UI가 변하는 것을 보고,
callbackSearch라는 state를 만들어 버튼에서 onClick이벤트가 일어나면 callbackSearch의 state값으로 search를 담아주고, 이를 Props로 전달해주었다.

filter와 includes를 활용하여 특정값만 map사용하기

function CardList(props) {
  return (
    <div className="cardList">
    
      {props.monsters
        .filter((monster) => monster.name.includes(props.search))
        .map((monster) => (
          <Card id={monster.id} name={monster.name} email={monster.email} />
        ))}

    </div>
  );
}


먼저, 내가 입력값을 onClick이벤트가 일어나면 Props로 전달해주었으니, CardList.js에는 위와 같이 "C"라는 키워드를 검색하면 이 키워드도 데이터와 함께 전달받게 된다. 이를 활용하여 먼저 데이터에서 filter를 활용해 search state에 담긴 값을 포함하고 있는 새로운 배열을 반환하고, 그 데이터를 가지고 Card라는 Component에게 id, name, email를 Props로 전달하고 map을 돌리게 된다.

추가

input에 value를 search state로 지정한 이유

 <button onClick={() => {
          setSearch("");
        }}
      >
        검색창 초기화
      </button>

input창의 value를 내가 원하는대로 만질 수 있다.

부족한점

  • filter를 사용하면 편하기는 하지만 모든 데이터를 다시 순회해야 한다는점(만약, 데이터가 엄청 많다면...)
  • input창에 이벤트가 일어날때마다 재랜더링이 일어난다는점
  • 가격낮은순, 가격높은순, 재구매많은순 등등을 어떻게 구현할 수 있을지에 대한 고민
profile
Always Awake

0개의 댓글