ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • StateAirline Client part-2
    FE 2023. 5. 31. 20:40

    Side Effect (부수 효과)

    React에서 컴포넌트내에 fetch를 사용해 API 정보를 가져오거나 이벤트를 활용해 DOM 직접 조작할 때 발생

    let foo = 'hello';
    
    function bar() {
      foo = 'world';
    }
    
    bar(); // bar는 Side Effect를 발생시킵니다!

     

    Pure Function (순수 함수)

    오직 함수의 입력만이 함수의 결과에 영향을 주는 함수. 입력으로 전달된 값을 수정하지 않음

    function upper(str) {
      return str.toUpperCase(); // toUpperCase 메소드는 원본을 수정하지 않습니다 (Immutable)
    }
    
    upper('hello') // 'HELLO'

     

    Effect Hook

    useEffect는 컴포넌트 내에서 side effect를 실행할 수 있게 하는 Hook인데 Side effect는 브라우저 API를 이용하며, 타이틀을 변경하는 것이다.

     

    API

    useEffect(함수) 첫 번째 인자는 함수이다. useEffect(함수, [종속성1, 종속성2, ...])

    함수가 실행될 때에는,

    • 컴포넌트 생성 후 처음 화면에 렌더링을 표시할 때
    • 컴포넌트에 새로운 props가 전달되며 렌더링
    • 컴포넌트에 상태(state)가 바뀌며 렌더링

    매번 새로운 컴포넌트가 렌더링 될 때 실행됨 (최상위에서만 호출하며, React 함수 내에서 호출한다)

    두 번째 인자는 배열인데 이 배열은 조건을 담고 있음. 종속성 배열은 어떤 값의 변경이 일어날 때 의미하며 배열엔 어떤 값의 목록이 들어간다. 배열을 빈 배열로 할 경우 컴포넌트가 처음 생성될 때만 effect 함수가 실행됨. 처음 외부 API를 통해 리소스를 받아오고 더 이상 API 호출이 필요하지 않을 때 사용

     

     

    AJAX 요청을 보낼 때

    useEffect(() => {
      fetch(`http://서버주소/proverbs?q=${filter}`)
        .then(resp => resp.json())
        .then(result => {
          setProverbs(result);
        });
    }, [filter]);

    엔드 포인트가 http://서버주소/proverbs일 경우.

     

    AJAX 요청이 느릴 경우

    외부 API 접속이 느릴 경우를 고려하여 로딩 화면의 구현은 필수이다. 상태처리 필요.

    const [isLoading, setIsLoading] = useState(true);
    
    // 생략, LoadingIndicator 컴포넌트는 별도로 구현했음을 가정합니다
    return {isLoading ? <LoadingIndicator /> : <div>로딩 완료 화면</div>}
    useEffect(() => {
      setIsLoading(true);
      fetch(`http://서버주소/proverbs?q=${filter}`)
        .then(resp => resp.json())
        .then(result => {
          setProverbs(result);
          setIsLoading(false);
        });
    }, [filter]);

     


     

    FlightDataApi.js

    import flightList from '../resource/flightList';
    import fetch from 'node-fetch';

    if (typeof window !== 'undefined') {
    localStorage.setItem('flight', JSON.stringify(flightList));
    }

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

    return fetch(`http://ec2-43-201-32-255.ap-northeast-2.compute.amazonaws.com/flight${params}`).then((response) => (response.json()));




    // 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);
    // });
    }

    .then은 Promise와 짝궁이며 이걸 펼칠 수 있게 해주는 것임. then이 뭘 의미하는지 알고 싶을 때 console.log로 확인해보기

     

    Main.js

    import Head from 'next/head';
    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';
    import Debug from './component/Debug';


    export default function Main() {
    // 항공편 검색 조건을 담고 있는 상태
    const [condition, setCondition] = useState({
    departure: 'ICN',
    });
    const [flightList, setFlightList] = useState([]);
    const [isloading, setloading] = useState(false)

    // 주어진 검색 키워드에 따라 condition 상태를 변경시켜주는 함수
    const search = ({ departure, destination }) => {
    if (
    condition.departure !== departure ||
    condition.destination !== destination
    ) {
    console.log('condition 상태를 변경시킵니다');
    setCondition({departure, destination});

    // TODO: search 함수가 전달 받아온 '항공편 검색 조건' 인자를 condition 상태에 적절하게 담아보세요.
    }
    };

    const filterByCondition = (flight) => {
    let pass = true;
    if (condition.departure) {
    pass = pass && flight.departure === condition.departure;
    }
    if (condition.destination) {
    pass = pass && flight.destination === condition.destination;
    }
    return pass;
    };

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

    // TODO: Effeck Hook을 이용해 AJAX 요청을 보내보세요.
    // TODO: 더불어, 네트워크 요청이 진행됨을 보여주는 로딩 컴포넌트(<LoadingIndicator/>)를 제공해보세요.
    useEffect(() => {
    setloading(true);
    getFlight(condition)
    .then((data) => setFlightList(data))
    .then(() => setloading(false))
    },[condition]) //condition이 바뀔 때마다 useEffect를 사용하겠다

    // TODO: 테스트 케이스의 지시에 따라 search 함수를 Search 컴포넌트로 내려주세요.
    return (
    <div>
    <Head>
    <title>States Airline</title>
    <link rel="icon" href="/favicon.ico" />
    </Head>

    <main>
    <h1>여행가고 싶을 땐, States Airline</h1>
    <Search onSearch={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>
    <img id="logo" alt="logo" src="codestates-logo.png" />
    </main>
    </div>
    );
    }

    useState를 사용해 false일 때, isloading과 재할당 할 수 있는 setloading을 주었다

    useEffect에서 setloading은 로딩을 시작하고 getFlight함수의 출발지와 도착지, setFlightList로 전체 데이터 목록을 불러오고 마지막 .then으로 로딩을  끝나며 condition이 바뀔 때마다 useEffect를 사용하는 것을 말한다. 

    'FE' 카테고리의 다른 글

    RefactorExpress  (0) 2023.06.02
    CORS  (0) 2023.06.01
    StateAirline Client part-1  (0) 2023.05.30
    Postman  (0) 2023.05.26
    [HTTP/네트워크] 실습  (0) 2023.05.25
Designed by Tistory.