[TIL] useEffect 활용과제(statesAirline-client)

징징징·2022년 8월 10일
2

React

목록 보기
3/5

📢 react Hooks인 useEffect와 fetchAPI를 이용해 서버에 요청을하여 사용자가 원하는 조건의 데이터만을 필터링하여 보여주는 과정을 진행했다.

아직 리액트의 흐름이 이해가 잘 안되어 페어분과 머리를 맞대고 아주 으쌰으쌰 진행해서 더 재밌게 진행한 것 같았다(물론 그만큼 힘들었음^^;)

  • 위 이미지에서 볼 수 있듯 여러 비행편 중 (출발지는 고정) 도착지를 검색조건으로 넣어줄 때, 그 검색조건에 해당하는 비행편만을 보이도록 하는 것이 목표인 과제였다!

💡PART 1 : 항공권 목록 필터링

테스트 조건과 URCLASS의 과제설명을 천천히 보며 진행했다. 처음에 갈피 잡는 것이 항상 어렵다🥹

  • PART1 다시 진행하며 헷갈린 부분은 마지막 테스트 조건인 '상태 변경 함수 search는 Search 컴포넌트의 '검색' 버튼 클릭 시 실행되어야 합니다' 였다.
const [condition, setCondition] = useState({
    departure: 'ICN',
  });

const search = ({ departure, destination }) => {
    if (
      condition.departure !== departure ||
      condition.destination !== destination
    ) {
      console.log('condition 상태를 변경시킵니다');
      setCondition({departure, destination});
    }
  };
  • useState를 이용하여 state인 condition과 업데이트함수인 setCondition을 만들어주고 이를 이용하여 search함수를 작성했다.

  • 사용자가 입력할 검색 조건인 departure와 destination 즉, 출발지와 도착지를 props(매개변수)로 전달해주며 state의 departure와 destination 이 props의 값과 다를 경우 setCondition 상태변경함수로 state의 값을 업데이트 해주었다.

  • JSX 코드 작성부분에 Search 컴포넌트를 연결해주는데 이 컴포넌트에 상태변경함수인 search를 onSearch라는 이름으로 전달해준다.

Pure Function(순수함수)

: 오직 함수의 입력만이 함수의 결과에 영향을 주는 함수를 의미한다.

  • 입력으로 전달된 값을 수정하지 않는다.
    (함수입력이 아닌 다른 값이 함수의 결과에 영향을 미치지 않아야 한다.)
  • 항상 똑같은 값이 리턴됨을 보장한다(side effect ❌)

Side Effect

: 함수 내 어떤 구현이 함수 외부에 영향을 끼치는 경우, side effect가 발생했다고 한다.

  • React에서는 컴포넌트 내 fetch를 사용해 API정보를 가져오거나 이벤트를 활용해 DOM을 직접 조작할 때 side effect가 발생했다고 한다.

💡 상태 끌어올리기

: 하위 컴포넌트에서의 어떤 이벤트로 인해 상위 컴포넌트의 상태가 바뀌는 것을 의미한다. 즉, 상위컴포넌트의 '상태를 변경하는 함수' 그 자체를 하위 컴포넌트로 전달하고, 전달된 이 함수를 하위 컴포넌트가 실행한다.

위의 Search 에 작성한 방법이 바로 상태 끌어올리기 라고 할 수 있다!
-> 상위 컴포넌트의 상태 변경 함수인 search를 하위 컴포넌트 즉 Search에(onSearch 라는 이름으로) 전달하고 이 함수를 하위 컴포넌트가 실행한다.

바로 이렇게!

  • textDestination (state) 와 setTextDestination (상태 변경 함수)을 useState로 만들어주고,

  • handleChange와 handleKeyPress라는 이벤트함수를 만들어주어 입력값(도착지)을 받으면 handleSearchClick이라는 함수를 호출해준다

  • 이 handleSearchClick 함수가 호출되면, 상위 컴포넌트로부터 전달받은 onSearch(search) 함수를 호출해주게되고, 고정된 출발지인 'ICN'과 입력값에 따라 다른 값이 될 textDestination을 매개변수로 전달하며 실행해준다!

-> 여기서 onSearch함수 실행에 departure와 destination의 값을 'ICN'과 'textDestination'을 전달해주는 부분을 생각해내는 게 조금 어려웠다..! 아마 흐름이 이해가 안된 상태에서 작성하려고 해서 그런것 같다. 당연히 입력받은 값을 전달해줘야하는것인데!! (이젠 이해완료😎)


💡PART 2 : AJAX 요청!

part2 테스트 조건에 비하면 part1은 이지- 했던 것이다...(😈)

먼저 FlightDataApi컴포넌트의 getFlight 함수가 무엇인가?

function getFlight(filterBy = {}) {
   let json = []; 
   if (typeof window !== 'undefined') { 
     json = localStorage.getItem('flight');
   }
   const flight = JSON.parse(json) || [];

   return new Promise((resolve) => {
     const filtered = flight.filter((flight) => {
       let condition = true;
      if (filterBy.departure) {
        condition = condition && (flight.departure === filterBy.departure);
       }
       if (filterBy.destination) {
       condition = condition && flight.destination === filterBy.destination;
     }
      return condition; 
    });
     setTimeout(() => {
      resolve(filtered);
    }, 500);
 });
  • getFlight 함수는 { filterBy=[] }라는 초기값을 가진다.
    -> getFlight함수의 매개변수로 값이 전달되면 전달된 값이 filterBy에 할당이되고, 값이 없다면 지정된 초기값을 가지게 된다.
  • getFlight 함수는 프로미스를 리턴한다.
    -> Main 컴포넌트에서 useEffect를 이용하여 getFlight함수로 상태를 변경할 수 있다.

  • getFlight이라는 함수는 프로미스를 반환하므로 비동기요청으로 볼 수 있으며, 이는 side effect이므로 useEffect를 사용해주어야 한다!

💡 useEffect 란?

: 컴포넌트 내에서 side effect를 실행할 수 있게하는 react의 Hook 이다.
(React Hooks => React 16.8 버전에서 새로 추가된 리액트 라이브러리 사용법!
추가 전에는 클래스를 통해 컴포넌트의 state를 관리하였으나, Hook이 추가됨으로써 함수형 컴포넌트에서도 state를 관리할 수 있게 됨)

  • useEffect(( ) => { })

  • 컴포넌트 내 모든 업데이트가 이루어질 때마다 렌더링이 된다. (default)

  • useEffect(( ) => { }, [])

    -> 이렇게 두 번째 인자(종속성)가 빈 배열로 주어지면, 처음 마운트 될 때 한 번만 렌더링이 이루어진다.

  • useEffect(( ) => { }, [count])

    -> 두 번째 인자인 종속성의 값이 주어지면, 그 요소가 업데이트 될 때마다 렌더링된다.

React Hooks 주의사항

  • 최상위에서만 호출해야한다.
  • React 함수 내에서 호출해주어야 한다.
    React 공식사이트
  • 다시 위의 useEffect 코드를 보면 condition 즉, 검색 조건이 업데이트 될 때만 렌더링이 되도록 종속성을 작성해주었다.
  • getFlight의 반환값(promise)을 .then으로 연결해주며 응답으로 받은 값을 setFlightList라는 상태변경함수에 전달해줌으로써 검색조건에 해당되는 값만 담긴 배열이 flight state에 저장된다. (=> 이는 다른 Flight컴포넌트를 통해 list화 될 것)

마지막 난관이었던 조건은 '검색 조건과 함께 StateAirline 서버에서 항공편 정보를 요청(fetch)한다'였다!

개념으로만 익혔던 fetch를 직접 써보는 시간😅
getFlight의 기존 코드블럭을 지우고 fetch를 이용한 요청문을 작성해보았다.

function getFlight(filterBy = {}) {
  return fetch(`http://ec2-13-124-90-231.ap-northeast-2.compute.amazonaws.com:81/flight?departure=ICN&destination=${filterBy.destination}`)
  .then(response => response.json());
  };

💡 Fetch(URL,{Options}).then(el => el.json( ))

-주어진 URL을 작성해줄 때 query parameter 를 이용하여 조건을 넣어주었다.

  • flight?departure=ICN&destination=${filterBy.destination}

-> 데이터의 flight의 departure가 ICN이면서 destination이 검색 조건으로 받아온 값인 요소들을 응답으로 보내주세요! 라는 요청이다! 이번 과제에서는 ICN이 고정값이므로 고정으로 작성해주었고 변동값인 destination만 템플릿 리터럴을 이용하여 작성해주었다👏

그리고 fetch는 promise를 리턴하기 때문에 then을 이용하여 응답은 받아주었고,
받은 응답(response)를 Web APIs인 response.json( )을 이용하여 자바스크립트의 형태로 받을 수 있게 리턴해주었다!

검색조건에 맞게 리스트들이 잘 나오게 되었다!👏👏👏

과제의 모든 것을 블로그에 남길 수 없기에(끝이 없음..)
페어분과 같이 진행했던 과제를 혼자 다시 진행해보며 계속해서 헷갈렸던 부분을 정리해보았다!

profile
꾸준히 나를 발전시키자 🫶

1개의 댓글

comment-user-thumbnail
2022년 8월 11일

와우 고생했네여

답글 달기