Project: States Airline Client

유슬기·2023년 2월 3일
0

프론트엔드

목록 보기
39/64
post-thumbnail

Main.js

import { useEffect, useState } from "react";
import { getFlight } from "../api/FlightDataApi";
import FlightList from "./component/FlightList";
import LoadingIndicator from "./component/LoadingIndicator";
import Search from "./component/Search";

export default function Main() {
	// 항공편 검색 조건을 담고 있는 state
  const [condition, setCondition] = useState({ departure: "ICN", });
	// 항공편 목록을 담고 있는 state
  const [flightList, setFlightList] = useState([]);
	// 로딩 여부(렌더링 완료 여부)를 담고 있는 state
  const [isLoading, setIsLoading] = useState(false);

  // 주어진 검색 키워드에 따라 condition 상태를 변경시켜주는 함수
  const search = ({ departure, destination }) => {
    if (
      // 새로 입력한 값(departure, destination 중 하나라도)이 기존 상태 값(condition 객체 내의 값)과 다를 경우 실행
      condition.departure !== departure ||
      condition.destination !== destination
    ) {
      setCondition({ departure, destination }); // 키: 값이 동일한 경우 축약 가능 (departure: departure, => departure,)
    }
  };

	// Effect Hook을 이용해 AJAX 요청 보내기, 로딩 상태에 따라 로딩 컴포넌트 제공
	// condition 조건이 바뀌면, Effect Hook에 의해 getFlight(condition) 함수가 호출
	useEffect(() => {
    setIsLoading(true); // data를 받아오기 전 로딩 상태를 true로 업데이트
    getFlight(condition).then(res => {
      setFlightList(res); // res를 받아와 그대로 fligthList 상태 업데이트
      setIsLoading(false); // 서버에서 data를 받아온 뒤니 로딩 상태를 false로 업데이트
    })
  },[condition]) 

	return (
	    <div>
	      <Head>
	        <title>States Airline</title>
	        <link rel="icon" href="/favicon.ico" />
	      </Head>
	
	      <main>
	        <h1>여행가고 싶을 땐, States Airline</h1>
	        <Search onSearch={search} />  {/* condition 상태변경 함수 전달 */}
	        <div className="table">
	          <div className="row-header">
	            <div className="col">출발</div>
	            <div className="col">도착</div>
	            <div className="col">출발 시각</div>
	            <div className="col">도착 시각</div>
	            <div className="col"></div>
	          </div>
						{/* 로딩 중이면 LoadingIndicator, 로딩이 끝나면 FlightList 렌더링 */}
	          {isLoading ? <LoadingIndicator /> : <FlightList list={flightList} />}
	        </div>
	      </main>
	    </div>
	  );
	}

Search.js

function Search({onSearch}) { // Main 컴포넌트에서 props로 onSearch 함수 전달받음(구조분해 할당)
	// 도착지를 담고 있는 state
	const [textDestination, setTextDestination] = useState(''); 

  const handleChange = (e) => { // 입력값 대문자 변환
    setTextDestination(e.target.value.toUpperCase());
  };

  const handleKeyPress = (e) => { // 엔터 키와 버튼 클릭을 감지
    if (e.type === 'keypress' && e.code === 'Enter') {
      handleSearchClick();
    }
  };

  const handleSearchClick = () => { 
    // 상위 컴포넌트(Main)에서 props를 받아서 실행
    onSearch({departure: 'ICN', destination: textDestination});
  };

  return (
    <fieldset>
      <legend>공항 코드를 입력하고, 검색하세요</legend>
      <span>출발지</span>
      <input id="input-departure" type="text" disabled value="ICN"></input>
      <span>도착지</span>
      <input
        id="input-destination"
        type="text"
        value={textDestination}
        onChange={handleChange}
        placeholder="CJU, BKK, PUS 중 하나를 입력하세요"
        onKeyPress={handleKeyPress}
      />
      <button id="search-btn" onClick={handleSearchClick}>
        검색
      </button>
    </fieldset>
  );
}

FlightDataApi.js

엔드포인트

http://ec2-13-124-90-231.ap-northeast-2.compute.amazonaws.com:81/

항공편 조회 Request

GET /flight

url 예시

http://ec2-13-124-90-231.ap-northeast-2.compute.amazonaws.com:81/flight?departure=ICN&destination=CJU

parameter

parameter형식설명필수 포함 여부
departure출발지 (문자열)특정 departure만 조회필수 아님
destination도착지 (문자열)특정 destination만 조회필수 아님
// filterBy로 들어오는 값: condition
export function getFlight(filterBy = {}) {
  let query = '';
  if (filterBy.departure) {
    query += `departure=${filterBy.departure}`;
  }
  if (filterBy.destination) {
    query += `&destination=${filterBy.destination}`
  }
  let url = `http://ec2-13-124-90-231.ap-northeast-2.compute.amazonaws.com:81/flight?${query}`

  return fetch(url).then(res => res.json()); // 패치를 통해 쿼리가 포함된 url data를 가져오기(.json() 사용하여 변환)
}

상태 끌어올리기

  1. Main 컴포넌트(상위) → Search 컴포넌트(하위)에 search함수를 전달한다.

    이 search함수는 주어진 검색 키워드에 따라 condition 상태를 변경한다.

  2. Search 컴포넌트에서 search함수를 구조분해할당으로 받는다. ({onSearch})

  3. 검색버튼을 누르거나 엔터를 치면 onSearch함수에 인자를 넣어 실행한다.

조건부 렌더링

삼항 연산자를 사용하여 조건부 렌더링 해준다.

여기서는 isLoading의 상태에 따라 isLoading이 true이면 로딩 인디케이터, false이면 FlightList 컴포 렌더링

  • isLoading이 true → 로딩 중 → getgetFlight로 데이터 받아오기 전
{isLoading ? <LoadingIndicator /> : <FlightList list={flightList} />}

Effect Hook

useEffect(() => {
    setIsLoding(true); // data를 받아오기 전 로딩 상태를 true로 업데이트
    getFlight(condition).then(res => {
      setFlightList(res); // res를 받아와 그대로 fligthList 상태 업데이트
      setIsLoding(false); // 서버에서 data를 받아온 뒤니 로딩 상태를 false로 업데이트
    })
  },[condition])

condition state가 업데이트 될 때마다 useEffect에 전달된 함수 호출

profile
아무것도 모르는 코린이

0개의 댓글