#TIL wecode Bootcamp Day 19(React fetch/lifecycle/map)

Jung Hyun Kim·2020년 6월 16일
0

wecode

목록 보기
21/42

React에서 fetch 이해하고, map과 filter 사용하여 검색기능 적용하기 💯


fetch()🔈

fetch는 필요한 데이터를 받아서 component형태로 사용할 때 주로 사용하는 방식이며 절차는 아래와 같다.

  1. 백엔드 서버를 호출해서 원하는 데이터(API) 를 받는다.
  2. 받은 데이터를 Component에 사용할 수 있도록 JSON을 JS로 변환한다.
  3. state에 저장해서 Component로 가져와 사용한다.

구조는 아래와 같은 형식이다.

아래의 경우는 get method로 불러올 때의 경우이고 , API를 불러오는 method가 post인 경우 method정보를 인자로 받아야 하기 때문에 API 주소형태가 다를 수 있다.

 fetch("http~~~~~1")//API 주소가 string 형태로 들어감 
.then(response => response.json())// JSON BODY를 JS로 변환해줌
.then((response) => this.setState ({users : response})
//받은 데이터를 user로 setState에 저장해줌, 보통이런형태로 사용되며, 
//데이터가 잘 들어온지 확인하려면 console.log로 확인해보면 된다. 

React Lifecycle의 이해와 fetch()의 위치☝🏼

React Lifecycle의 전체 과정



Mount와 UnMount의미

  • Mount컴포넌트가 호출되는 상태 (DOM 으로 들어간 상태) 를 의미하며, UnMount컴포넌트가 더 이상 필요 없는 상태를 의미한다.

  • Mounting

    : constructor 함수가 실행되면, render 되고 그후에 componentDidMount가 실행된다.
    : setState가 새로 업데이트 되면 re-render 되기 때문에 fetch 함수의 가장 좋은 위치는 componentDidMount 함수 자리이다. 🔔



  • Updating

    : propsstate 값에 변화가 일어 났을 때,아래가 re-render 되게된다. 기본적으로 우리가 다루고 아는 부분은 render()가 re-render 된다는 부분 이지만 다른 method가 있다면 아래 해당하는 method도 다시 업데이트가 되는 것 이다.
    • render()
    • componentDidUpdate()
    • static getDerivedStateFromProps()
    • shouldComponentUpdate()
    • getSnapshotBeforeUpdate()

  • Unmounting

    : DOM에서 해당 Component를 제거 할 때 사용 된다.
    - componentWillUnmount()
    : 보통 timers 를 무효화 시키거나, newwork request를 없앨 때, 인데, setState()를 통해 상태를 업데이트하는것이 아니다. 왜냐하면 re-render 시키려는게 아니라 아예 없애려고 하는 기능이기 때문이다.

    도움되는 블로그
    공식 문서

  • Fetch는 한번만 불러와야 하기 때문에 render 안에 위치하면 loop이 돌 수 있다. 그렇기 때문에 한번 render 되는 ComponentDidMount()에 위치시켜야 한다.

  • 사용 예시

ComponentDidMount() {
fetch();
.then((response) => response.json() )
.then((response) => this.setState ({users : response})



React Map 과제 해보기🎫🎫🎫

👉🏼 구현 하고자 하는 기능

  1. 전체 프로필 정보가 있는 JSON DATA를 fetch함수를 사용하여 가져온다.
  2. CardList component에 mosters라는 이름의 props로 저장한다.
  3. Search bar를 input OnChange event를 적용해 입력 값을 setState로 저장한다.
  4. Search bar에 검색 기능을 사용할 수 있게끔 filter 기능을 적용해서, 검색하는 카드가 화면에 보여지게끔 한다.

👉 전체 파일 구조 확인

  • 먼저 전체 화면에 검색창, 카드리스트들이 들어가야 하므로 크게 CardList, Card, SearchBox components 들이 필요 하고, 전체를 나타내줄, index.js가 있어야 하겠다. (각각의 css 파일 또한 기본)
  • Card의 부모가 CardList, CardList가 불려지는 곳이 index.js 라고 생각하면 된다.

☝🏼 API 호출을 통해 필요한 데이터 불러오기

  • 이전에 작성해보았던 Lifecycle을 고려해 보았을 때, API호출은 componentDidMount() 안에 위치하게 해야한다. (API호출은 딱 한번만 render 해야 되기 때문)

  • 호출 할 api주소를 ' '안에 작성하고, .then 함수를 통해 받은 JSON을 JS로 변환해주고, .then 함수를 다시 호출해서 받은 데이터를 이전에 this.state에 빈 객체로 설정해준 monsters 객체에 저장해준다.

state = {
mosnters : []
}

componentDidMount() {
  fetch('https://jsonplaceholder.typicode.com/users')
  .then(res => res.json())
  .then(res => this.setState ({monsters : res}))
}

☝ CardList component에 mosters라는 이름의 props로 저장한다.

  • index.js. 파일내의 return 되어야 하는 곳에 CardList component를 만들어 주고, monsters라는 이름의 props를 주고, 그 안에 state에 저장해준 monsters 데이터를 전달해준다.
<CardList monsters={this.state.monsters}/>

☝ Card를 component로 받는 CardList.js 파일에 보여주고자 하는정보를 넣어준다.

현재는 정보를 통해 이름,이메일,이미지,를 포함한 10가지의 정보만 들어왔지만 우리가 필요한 정보만 보여주게끔 보여주고 싶은 키 값만 가져오면 된다

  • CardList component에 Card component를 전달해준다. Card.js에 담긴 내용은 아래인데, this.props.id this.props.name, this.props.email을 통해 props 값을 가져온다고 정의해 두었으니, Card component에서 id,name,email이름을 주고 필요한 정보를 불러 와야 한다.

  • Card.js 코드

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

export default Card;


☝ map 함수를 사용하여, 화면에 렌더하고자 하는 카드 리스트를 전달 해 준다.

  • Card component를 import하고, CardList.js 파일에 전달하고자 하는 키 값을 부모인 index.js로 부터 가져온 값 (this.props.monsters) 에 map 함수로 접근한다.

  • map 함수를 사용해서 monsters 데이터 객체 하나하나에 접근하여 보여주고 싶은 데이터를 출력하면 된다. (monsters는 데이터를 포함한 여러객체를 가지고 있는 array 이다. monsters = [ { },{ },{ } ] 이렇게 생겼기 때문에 인자 값 을 주고 가져오고자 하는 값을 dot notation을 통해 가져오면 된다.

  • 각 { } 을 돌면서 <Card component>에 원하는 값을 포함시켜서 출력하게 끔 하는 상태라고 보면된다. 나는 item을 인자 값으로 주어서 각 객체의 .id, .name .email 을 가져오는 식으로 표현 한 것이다.

import React, { Component } from "react";
import "./CardList.css";
import Card from "../Card/Card"; // Card를 import 한다 

class CardList extends Component {

  render() {
    return (
    <div className="card-list">
      {this.props.monsters.map((item,idx) => { return (
    <Card key={idx} id ={item.id} name={item.name} email={item.email} />
        )})}
    </div>
    )
    
}
}
export default CardList;
  • map 함수 로 컴포넌트 재사용 시 두가지 인자를 넣어줄 때 두번째 값은 index를 의미한다.

  • React 에서 컴포넌트에서 재사용 시 unique한 key 값을 설정하지 않으면, 코드는 렌더링 되지만 console에서 key 값이 설정되지 않았다는 오류(*Each child in an array should have a unique "key" prop*) 가 뜬다. 항상 unique한 키 값을 설정해 주어야 한다. 👀

  • 현재 카드에서 unique한 요소를 찾지못해 index로 저장했는데 아래 블로그를 보니 index값으로 저장하는 것인 좋은 practice는 아니라고 한다. 참고 블로그

  • React에서 key는 DOM element를 idenify할 수 있는 유일한 요소이기 때문에 중간에 추가 되거나, 삭제되는 데이터가 있을 때, 키 값이 그대로이면 오류를 발생할 가능성이 높다. a key is the only thing React uses to identify DOM elements. What happens if you push an item to the list or remove something in the middle? If the key is same as before React assumes that the DOM element represents the same component as before. But that is no longer true.

  • 최대한 가진 데이터 에서 key 값을 지정해 사용하는 걸로 인식하고 있어야겠다.



☝ Search bar 구현

  • 검색 기능을 구현해 줄 input 을 별도의 SearchBox 컴포넌트 안에 만들고 index.js에 원하는 위치에 component로 전달 해준다.
  • onChange event를 적용해서 입력 값을 setState의 UserInput에 저장할 수 있게 끔 한다.
  • SearchBox.js 파일을 아래와 같이 설정하고 onchange에 부모값의 handleChange를 가져오게 한다.
import React, { Component } from "react";
import "./SearchBox.css";

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

export default SearchBox;
  • index.js로 가서 SearchBox에 handleChange 를 주고 그 값으로 this.handleChange 를 입력해, 원하는 함수(this.handleChange) 를 render() 위에 구현 해준다.
  state = {
    monsters: [],
    userInput: ""
  };
-------------------------------
  handleChange = (e) => {
  this.setState({userInput : e.target.value})
}
-------------------------------
<SearchBox handleChange={this.handleChange}/>


☝ Search bar에 검색 기능을 사용할 수 있게끔 filter method를 적용해서, 검색하는 카드가 화면에 보여지게끔 한다.

순서대로 보자면...

  1. monsters 객체의 각 요소에 접근해 각 요소의 name 값이, userInput 값에 포함 되는 요소라면 filter해서 return 하게 하고 그 return 된 값을 monstersFilter에 저장 한다.

  2. 그냥 입력할때는 보통 소문자로 입력하기 때문에 각 요소의 name값에 toLowerCase()해주는 것이다.

const monstersFilter = this.state.monsters.filter((obj) => 
      obj.name.toLowerCase().includes(this.state.userInput.toLowerCase()));
  1. 기존에 this.state.monsters로 정해줬던 Cardlist 의 props 값을 filter 메소드가 반환하는 변수로 저장한다.
<CardList monsters={monstersFilter}/>



React method (map,filter)를 사용한 과제를 구현해 보았는데 부족한 점은 더 블로깅 하고 넘어가서 새로운 프로젝트를 준비할 수있도록 해야겠다.
정리할 땐 아하! 하다가도 실제 다른 코드로 구현 하면 아직은 부족하므로..ㅜㅜ 다시 더 보고 볼것! 💁

profile
코린이 프론트엔드 개발자💻💛🤙🏼

0개의 댓글