westagram 클론 Mock data를 이용한 검색창 구현

김태현·2020년 11월 10일
0

연습장

목록 보기
7/7

먼저 우리가 불러올 mock data를 json 형식으로 만들어 준다

public폴더 밑에 data폴더 밑에 data.json 파일을 만들고 내용은 아래와 같이 적는다.

{
  "data": [
  { 
    "id": 1, 
    "name": "wecode_bootcamp", 
    "description": "wecode | 위코드" 
  },
  { 
    "id": 2, 
    "name": "wecode_founder", 
    "description": "송은우 (Eun Woo Song)" 
  },
  { 
    "id": 3, 
    "name": "wecode_korea", 
    "description": "" 
  },
  { 
    "id": 4, 
    "name": "Wecode", 
    "description": "강남구 테헤란로 427,서울" 
  }
]
}

그럼 이제 componentDidMount(일명 컨디마)와 fetch 함수를 이용하여 받아온 데이터를 state에 저장한다.

componentDidMount() {
  fetch("http://localhost:3000/data/data.json", {
    method: "GET"
  })
  .then(res => res.json())
  .then(res => {
    this.setState({
      users: res.data,
    })
  })
}

여기서 componentDidMount를 쓴 이유는 우리가 불러올 데이터가 매우 큰 경우에는 일반적으로 불러오면 비효율적이기 때문이다.
리액트 특성상 state가 바뀔때마다 화면이 렌더되므로 이때 계속 큰 데이터가 받아지면 안좋기 때문이다!
따라서 constructor, render 이후에 한번만 렌더링 되는 componentDidMount를 이용하여 이를 처리한다!
그리고 그 안에다가 fetch 함수를 쓰는데 아까도 말했듯이 큰 데이터를 불러오는 것이기 때문에 비동기 처리를 해야한다
비동기처리란 가령 우리가 큰 데이터가 받아질 때 동안 기다리면 전체적인 작업도 느려지고 비효율적이니 워커라는 공간에 이렇게 큰 시간이 필요한 작업들을 보내놓고 그 다음 작업들을 하다가 그 사이에 워커에 보내놓은 작업이 완료가되면 그걸 다시 받아서 다시 완료하고 진행하는 것을 말한다!
이 비동기 작업을 fetch 함수가 담당을 한다

fetch 함수 안에는 첫번째 인자로 API주소를 쓰고, 두번째 인자로는 method를 쓴다.
우리는 데이터를 가져와서 가공하기만 할것이므로 GET을 썼다. 다시 보내려면 POST를 씀!

그 다음엔 then이 보이는데 이것은 비동기인 fetch 함수 내에서의 작업을 동기적으로 하기 위함이다!
말이 좀 어려운데 fetch 함수 자체는 비동기 이지만! 그 안에서 하는 작업들은 동기적으로 처리하기 위해서 사용한다고 보면 된다!

첫번째 res에는 string 타입의 데이터가 들어있고 이걸 .json()을 이용하여 json 타입으로 변환 시킨다.
두번째 then을 통한 res는 이렇게 변환된 정보가 들어있게 되고 이를 setState 해서 users의 state를 교체해준다.

그 다음은 button에 onClick 이벤트를 만들어서 show_search의 state를 토글형식으로 바뀌게 해주었다.

<button onClick={() => this.setState({show_search: !show_search})}>검색</button>

여기서 포인트는 콜백함수로 적어줘야 한다는 것이다!
그냥 적으면 버튼을 클릭할 때 바로 setState가 동작하기 때문에 우리가 원하는 결과를 얻기가 어렵다!

그리고나서 이제 검색창 부분인데
input에 onKeyUp 이벤트를 걸어서 입력한 값으로 화면을 보여주도록 만들려고 한다 ~

key_up_event = (e) => {
  const { show_search, users } = this.state;
  const value = e.target.value;
  
 if(users) {
   const result = users.filter((el) => {
     return el.description.includes(value)
   })
   
   this.setState({
     result: result,
   
   })
 }
}

먼저 e.target.value를 받아서 변수 value에 넣고
users가 존재하면 users를 filter를 돌려서 includes 함수를 이용해 입력한 값을 포함하는 배열을 반환하도록 만들어주었다, 그리고 이걸 다시 변수 result에 저장!

여기서 if(users) 이 조건은 우리가 users를 componenetDidMount로 받아오기 때문에 리액트 라이프사이클 순서상 constructor => render => componentDidMount 이므로 users에 값이 있을때 동작시키기 위함이다!
왜냐하면 처음에는 render가 먼저되기 때문에 users엔 우리가 초기화한 빈배열만 있기 때문이다!

filter 안에 return 부분을 보면 el.description 이 부분은 우리가 제일 처음에 작성했던 json 파일에서 description 부분을 가져온다는 말이다!

그리고 이 과정을 거치고 나면 setState를 해서 result 값을 갱신해주고
최종적으로 버튼을 동작시킬 때 바꾼 show_search의 불리언 값으로 result에 map을 돌려서 태그들을 만들어준다

이렇게 말이다~~

{show_search 
  ? this.state.result.map((el) => {
  	return (
      <div className="search_list">
        <p>
          {el.name}
          <span>{el.description}</span>
        </p>
      </div>
    );
  })
 : ""}

느낀점
mock data를 받아오는 과정 때문에 그리고 그것 때문에 쓴 componentDidMount 때문에 중간에 state 하나 더 만들어줘서 값을 교체를 해준게 인상적이었다!!
검색창 구현은 언제해도 가장 어려운것 같다 ~
지금은 간단하게 includes 함수를 이용해서 입력한 값이 포함이 되어있는지만 로직을 짰는데
나중에 정규표현식을 이용해서 어떻게 더 세부적으로 검색기능을 만들 수 있지 않을까 생각을 해봄.

profile
프론트엔드 개발자

0개의 댓글