본문 바로가기
Coding/REACT

[React] component, state, props, useEffect 연습 ( Monsters )

by 하상원이야 2022. 6. 18.

Monsters

1. fetch를 이용해서 API 데이터(객체 배열)를 불러오고, 그 데이터를 state에 저장한다.

2. state를 자식 컴포넌트에게 props 를 사용하여 값을 전달해준다.

3. 자식 컴포넌트에서 map 함수로 배열을 화면에 나타내고, 그 자식 컴포넌트에서 각 객체의 키 값으로 각 배열의 정보를 불러온다.

4. 검색 창을 만들어 입력 값을 받고, filter 함수로 검색 창의 입력 값과 동일한 name 값을 가진 요소만 나타나게 해준다.

의 과정으로 구성된 연습 페이지이다 !

 

fetch 로 API 가져오기.  useEffecf 의 종속 배열을 []로 주어서 렌더링 시 처음에만 실행되게 했다.

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users", { method: "GET" })
      .then((res) => res.json())
      .then((data) => {
        setMonsters(data);		// 가져온 API를 monsters state에 저장
        setSearchedMonsters(data);	// 검색되는 monsters array
      });
  }, []);

검색했을 때 filter하여 화면에 표현하는 이벤트가 onChange기 때문에, 초기 값이 비어있으면 화면에 나타나지 않는다.

그래서 searchedMonsters도 초기 값으로 가져온 데이터 값을 주었다.

 

검색 창 구현

  // SearchBox 에 props로 넘겨줄 handleChange 메소드 정의
  const handleChange = (e) => {
    setSearchedMonsters(monsters.filter((vals) => 
    vals.name.toLowerCase().includes(e.target.value)));
  };

필터의 monsters 배열에 각 항목(val)의 이름(.name)의 

소문자(.toLowerCase())를 포함하는가(includes

인풋 값의 value(이벤트 핸들러가 검색 창에 있다)

포함하는(true) 요소만으로 새 배열이 만들어진다(filter)
그걸 searchedMonsters에 저장한다(setSearchedMonsters)

 

Monsters.js

  return (
    <div className="monsters">
      <h1>컴포넌트 재사용 연습!</h1>
      <SearchBox handleChange={handleChange} />
      <CardList monsters={searchedMonsters} />
    </div>
  );

검색창엔 인풋 값을 filter해서 searchedMonsters 배열에 저장하는 함수를 전달하고

CardList엔 검색된 monsters 배열을 전달한다

 

SearchBox.js

function SearchBox(props) {
  return <input className="search" type="search" 
  placeholder="Search..." onChange={props.handleChange} />;
}

search input에 onChange 이벤트로 필터링된 searchedMonsters 배열 저장 함수를 실행하게 했다

input type에 search 타입이 있다는 걸 처음 알게 되었다. value를 지우는 X 버튼이 내장되어 있었다 !!

 

CardList.js

const CardList = ({ monsters }) => {
  return (
    <div className="cardList">
      {monsters.map((el) => {
        return <Card key={el.id} el={el} />;
      })}
    </div>
  );
};

카드리스트 컴포넌트에선 monsters 배열을 map 함수로 반복하게 했다. key 값은 아이디를 사용했다 ! 

그리고 부모 컴포넌트에서 searchedMonsters를 monsters 라고 해줘서 사실 searchedMonsters 배열을 map 하고 있다

 

Card.js

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

카드 컴포넌트에선 이미지와 이름, 이메일을 각 map에서 받은 el 객체의 키 값으로 불러냈다. 

` ` 백틱을 사용하면 따옴표와 같은 역할을 하는데, 안에 ${}를 사용해서 변수를 적용할 수 있다 !!

맥북 키보드에선 안보이는데 한/영 키를 눌러서 영어 상태에서 ₩(~)를 누르면 나온다 !!

 

 

가장 어려웠던 점은 state이다 !  개념이 부족했다 !

input 값을 받는 state와 input 값을 filter한 배열 state를 하나의 함수에 넣었었는데,

state는 현재 중괄호가 끝나고 값이 바뀐다는 것을 모르고 있어서,

검색 값이 input 값에 비해 한 글자 씩 밀려서 인식하는 걸 고치는데 애먹었다.

(현재 input 값이 적용되기 전 기준으로 filter를 하기 때문에)

 

나이스 !

반응형

댓글