TIL 23

모모·2021년 12월 28일
0

TIL

목록 보기
23/28

React 실습: 데이터 흐름을 이해하고 비동기 요청 처리하기

Main 컴포넌트

export default function Main() {
  const [condition, setCondition] = useState({
    departure: 'ICN'
  })
  const [flightList, setFlightList] = useState(json)

  const search = ({ departure, destination }) => {
    if (condition.departure !== departure || condition.destination !== destination) {

      setCondition({ departure: departure, destination: destination})
      // 함수를 정의하는 부분의 파라미터이기 때문에, 무엇이 인자로 들어와야 하는지 가이드만 주는 것
    }
  }

  const [isLoading, setIsLoading] = useState(false);

  useEffect(
    () => {
      setIsLoading(true);
      getFlight(condition) // 프로미스를 리턴함. 하지만 이 단계에서는 아직 현황판일뿐임
      .then((result) =>  // 검색 조건을 거친 결과를 가지고,
        setFlightList(result)) // 항공편 리스트를 업데이트 해줘야 함
      .then(() =>{
        setIsLoading(false) // 첫 번째 then의 바디로 옮겨도 상관없음
      })
      }
    , [condition] // condition이 바뀔 때마다 리렌더링
  )


  global.search = search // 실행에는 전혀 지장이 없지만, 테스트를 위해 필요한 코드입니다. 이 코드는 지우지 마세요!

  return (
    <div>
      <Head>
        <title>States Airline</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main>
        <h1>
          여행가고 싶을 땐, States Airline
        </h1>
        <Search onSearch={search} />
        {/* Search 컴포넌트의 이벤트가 Main 컴포넌트의 상태를 바꾸는 구조임.
        Main 컴포넌트의 "상태를 변경시키는 함수" search를 onSearch props로 전달하고,
        Search 컴포넌트에서 해당 함수로 동작을 실행하는 형태를 취함으로써
        상위에서 하위로의 단방향 데이터 흐름 원칙을 지킬 수 있음*/}
        <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>
          {isLoading ? <LoadingIndicator /> : <FlightList list={flightList} />}
        </div>

        <div className="debug-area">
          <Debug condition={condition} />
        </div>
      </main>
    </div>
  )
}

Search 컴포넌트

function Search({ onSearch }) {
  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 = () => {
    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>
}

export default Search

FlightDataApi.js

if (typeof window !== "undefined") {
  localStorage.setItem('flight', JSON.stringify(flightList)); // flightList JSON문자열로 바꾼 것을 value로, flight를 key로 해서 localStorage에 추가
}

export function getFlight(filterBy = {}) { // (filterBy)
  // HINT: 가장 마지막 테스트를 통과하기 위해, fetch를 이용합니다. 아래 구현은 완전히 삭제되어도 상관없습니다.
  // TODO: 아래 구현을 REST API 호출로 대체하세요.

  let url = "http://ec2-13-124-90-231.ap-northeast-2.compute.amazonaws.com:81/flight?departure=ICN"

  if(filterBy.destination){
    url = `${url}&destination=${filterBy.destination}`
  }

  return fetch(url)
  // .then((response) => console.log(response))
  // json()메소드 사용 전에는 Response 객체임
  .then((response) => response.json())

  {/*
  let json = []
  if (typeof window !== "undefined") {
    json = localStorage.getItem("flight"); // localStorage에서 flight key의 value를 가져옴
  }
  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);
  });
}
*/}

참고: Default Parameter

JavaScript에서, 함수의 매개변수는 undefined가 기본입니다. 그러나, 일부 상황에서는 다른 기본 값을 설정하는 것이 유용할 수 있습니다. 이때가 바로 기본값 매개변수가 필요할 때 입니다.
다음 예제에서, multiply호출시 b에 할당된 값이 없다면, b 값은 a*b를 평가할 때 undefined일 거고 multiply 호출은 NaN이 반환됩니다.

function multiply(a, b = 1) {
  return a*b
}
multiply(5, 2)          // 10
multiply(5)             // 5
multiply(5, undefined)  // 5

0개의 댓글