TIL DAY.28 [React] Monsters 과제 filter 메소드 활용하면서 복습

Dan·2020년 9월 29일
0

리액트

목록 보기
9/17
post-thumbnail

추석 연휴 덕분에 쉬면서 내가 약했던 부분을 그나마 되돌아가서 복습할 수 있는 시간이 생겼다.
오늘은 1차 팀 프로젝트를 진행하면서도 제일 어렵다고 느꼈던 Array.map() 그리고 부모,자식 컴포넌트를 활용한 state,props 그리고 마지막으로 filter메소드를 복습해보는 시간을 가져볼려고한다.

일단 부모-자식 간의 컴포넌트 활용을 하기 위해서는 먼저 React의 Life cycle에 대해서 이해할 필요성이 있다.

React Lifecycle 기본순서

아래는 위의 코드실행 결과가 콘솔에 찍히는 순서이다.

  1. constructor
  2. render
  3. componentDidMount
  4. fetch 완료
  5. render
  6. (setState)
  7. componentDidUdate (setState 되었기 때문에 컴포넌트 업데이트 발생)
  8. componentWillUnmount (만약 존재한다면)

자 이제 몬스터 과제로 다시 돌아가보자,

TASK 1.

API 주소: https://jsonplaceholder.typicode.com/users

위 주소를 호출하여 데이터 로딩을 처리해주세요!
- componentDidMount()
- fetch
- setState (monsters 에 저장)

class Monsters extends Component {
  state = {
    monsters: [],
    userInput: "",
  };

  componentDidMount() {
    fetch("https://jsonplaceholder.typicode.com/users", {
      method: "GET",
    })
      .then((res) => res.json())
      .then((res) => {
        this.setState({ monsters: res });
      });
  }
   render() {
    return (
      <div className="Monsters">
        <h1>컴포넌트 재사용 연습!</h1>
        <CardList monsters=this.state.monsters />
      </div>
    );
  }
}

export default Monsters;

위에서 공부 한 기본적인 라이프 사이클에 의하면 먼저 state에 있는 빈 monsters 배열을 render 해올 것이다. 그 다음에 componentDidMount에 들어가서 주어진 주소를 fetch 해온 다음 response 를 setState를 통해 monsters의 배열을 채워줄 것이다. 그 다음 CardList라는 자식 컴포넌트에 monsters라는 state를 props로 넘겨줄 것이다.

TASK 2.

Card 컴포넌트를 import 한 뒤, props로 내려받은 데이터에
map 함수를 호출해 각각 다른 데이터를 가진 Card 컴포넌트들을 리턴해주세요!
Card 컴포넌트에서 필요로 하는 데이터는 id, name, email 입니다.

class CardList extends Component {
  render() {
    const { monsters } = this.props;
    return (
      <div className="card-list">
        {monsters.map((monster) => {
          return (
            <Card
              key={monster.id}
              id={monster.id}
              cardName={monster.name}
              cardEmail={monster.email}
            />
          );
        })}
      </div>
    );
  }
}

export default CardList;

위에서 Monsters.js 부모 컴포넌트로부터 전달 받은 monsters 배열값을 map함수를 이용해서 호출하여 각각 다른 데이터를 가진 Card 컴포넌트를 리턴 할 수 있다. Card 컴포넌트로부터 필요한 데이터는 id, name, email 뿐이므로 map을 돌리면 인자값을 monster로 지정해주고 id={monster.id} 같은 방식을 통해 배열에서 원하는 데이터만 출력될 수 있도록 만들 수 있다. 여기서 map 함수를 이용할 때 index 값을 따로 지정해줘야만 하는데 Card의 data 안에 이미 index값들이 id로 지정되어 있어서 따로 index 값을 정의할 필요가 없다.

TASK 3.

Card 컴포넌트 구조
image tag => < src=이미지주소 alt="">

  <h2>Name</h2>
  <p>Email</p>

Card 컴포넌트에서 props로 받아야하는 데이터는 id, name, email 입니다.
props에서 해당하는 키값들을 추출하여 위와 같은 구조로 만들어주세요!

이미지주소: https://robohash.org/${숫자}?set=set2&size=180x180
카드마다 다른 이미지를 보여주기 위해
위 주소의 숫자 부분을 props로 내려받은 id로 대체하셔야 합니다.

Name 과 Email 도 마찬가지입니다.

class Card extends Component {
render() {
  const { id, cardName, cardEmail } = this.props;
  return (
    <div className="card-container">
      <img src={`https://robohash.org/${id}?set=set2&size=180x180`} alt="" />
      <h2>{cardName}</h2>
      <p>{cardEmail}</p>
    </div>
  );
}
}

export default Card;

Card 컴포넌트로 부터 id, name, email을 받기 위해서 props를 활용하여 내려받습니다. 이 때 props의 키값들은 CardList에서 Card 컴포넌트에 지정해줬던 키값 이름과 동일해야만 합니다. 또한 id 의 img를 가져오는 과정에서 배열이 맵을 통해 돌면서 지속적으로 url주소가 바껴야함으로 templete literal 을 활용하여 id값만 유동적으로 바뀔수 있게 설정해줘야 한다.

Task 4.

- SearchBox 컴포넌트에 정의한 handleChange 메소드를 넘겨주고,
호출 시 인자로 들어오는 이벤트객체(e)를 활용해 userInput 으로 setState.

- 필터링 로직 구현 (filter 메소드 활용)
여기서 비교 대상은 monster 객체의 name 값입니다.
소문자로 바꾼 monster.name 값과 userInput값을 비교.
filter 메소드가 반환하는 값을 변수에 저장 후 return 문 안에 CardList에 props로 전달

SearchBox .JS

class SearchBox extends Component {
  render() {
    return (
      <input
        className="search"
        type="search"
        placeholder="Search..."
        onChange={this.props.handleChange}
      />
    );
  }
}

export default SearchBox;

Monsters.JS

class Monsters extends Component {
  state = {
    monsters: [],
    userInput: "",
  };
  // 데이터 로딩
  componentDidMount() {
    fetch("https://jsonplaceholder.typicode.com/users", {
      method: "GET",
    })
      .then((res) => res.json())
      .then((res) => {
        this.setState({ monsters: res });
      });
  }



  // SearchBox 에 props로 넘겨줄 handleChange 메소드 정의
  handleChange = (e) => {
    const { value } = e.target;
    this.setState({
      userInput: value,
    });
  };

  render() {
    const filterMonster = this.state.monsters.filter((monster) =>
      monster.name.toLowerCase().includes(this.state.userInput.toLowerCase())
    );
    return (
      <div className="Monsters">
        <h1>컴포넌트 재사용 연습!</h1>
        <SearchBox handleChange={this.handleChange} />
        <CardList monsters={filterMonster} />
      </div>
    );
  }
}

export default Monsters;

SearchBox의 value 값을 handleChange를 통해 userInput로 지정해줘서 searchbox에 유저가 글자를 쓸 때마다 정보를 searchbox 컴포넌트에서 props로 받아온다. 받아온 글자 정보를 filter를 통해 monster.name 의 소문자와 userInput 소문자 정보가 동일할 때만 지정해둔 CardList 컴포넌트로 넘어가서 해당 정보를 map 함수를 통해 돌린다. 결국 유저가 쓴 정보와 동일한 값을 갖고 있는 배열만 출력되게 되고 그것이 바로 search 기능이다.

profile
만들고 싶은게 많은 개발자

0개의 댓글