-
[React] ์ค์ต - StatesAirline ClientcodeStates front-end/React 2023. 2. 4. 16:52๋ฐ์ํ
๐ StatesAirline Client
๐ ํ์ต ๋ชฉํ
Part - 1
[React] ๋ฐ์ดํฐ ํ๋ฆ
๐๋ฆฌ์กํธ ๋ฐ์ดํฐ ํ๋ฆ ๐๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ํ๋ฆ( one-way data flow ) React๋ ํ์ด์ง ๋จ์๊ฐ x -> ์ปดํฌ๋ํธ ๋จ์ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๊ณ -> ํ์ด์ง๋ฅผ ์กฐ๋ฆฝ (์ํฅ์(bottom-up)์ผ๋ก ์ปดํฌ๋ํธ ๊ตฌ์กฐ๋ฅผ ์ง ๋ค) ์ปดํฌ๋
hwantech.tistory.com
Part - 2
[React] Effect Hook
๐Effect Hook React ์ปดํฌ๋ํธ ์ธ๋ถ์์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ณ ๋ฐ์์ค๋ ๊ณผ์ ๐Side Effect (๋ถ์ ํจ๊ณผ) React์์ ์ปดํฌ๋ํ ๋ด์์ fetch๋ฅผ ์ฌ์ฉํด API ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ ์ด๋ฒคํธ๋ฅผ ํ์ฉํด DOM ์ง์ ์กฐ์ํ
hwantech.tistory.com
Part 1 - Test
- Main ์ปดํฌ๋ํธ ๋ด search ํจ์๋ ๊ฒ์ ์กฐ๊ฑด์ ๋ด๊ณ ์๋ ์ํ ๊ฐ์ฒด condition์ ์ ๋ฐ์ดํธํด์ผ ํฉ๋๋ค
const search = ({ departure, destination }) => { if ( condition.departure !== departure || condition.destination !== destination ) { console.log('condition ์ํ๋ฅผ ๋ณ๊ฒฝ์ํต๋๋ค'); // TODO: search ํจ์๊ฐ ์ ๋ฌ ๋ฐ์์จ 'ํญ๊ณตํธ ๊ฒ์ ์กฐ๊ฑด' ์ธ์๋ฅผ condition ์ํ์ ์ ์ ํ๊ฒ ๋ด์๋ณด์ธ์. } };
condition์ ์ ๋ฐ์ดํธ -> state์ ์ํ๋ฅผ ๊ฐฑ์ ํด์ผํ๋ค
condition์ ์ด๊ธฐ๊ฐ์ departure: 'ICN' ์ถ๋ฐ ์ ๋ณด๋ง ๋ด๊ฒจ ์์
์ด ๋ง์ ์ถ๋ฐ์ง๋ ICN์ผ๋ก ์ ํด์ ธ ์๊ณ destination์ ์ ํด์ง์ง ์์๋ค
์ด๋ฅผ ์ ๋ฐ์ดํธ ํด์ฃผ๊ธฐ ์ํด์ setCondition์ผ๋ก condition ๊ฐ์ ๋ฐ๊พธ์ด ์ค์ผ ํ๋ค
const search = ({ departure, destination }) => { if ( condition.departure !== departure || condition.destination !== destination ) { console.log('condition ์ํ๋ฅผ ๋ณ๊ฒฝ์ํต๋๋ค'); // TODO: search ํจ์๊ฐ ์ ๋ฌ ๋ฐ์์จ 'ํญ๊ณตํธ ๊ฒ์ ์กฐ๊ฑด' ์ธ์๋ฅผ condition ์ํ์ ์ ์ ํ๊ฒ ๋ด์๋ณด์ธ์. setCondition({departure, destination}) } };
- Search ์ปดํฌ๋ํธ์๋ ์ํ ๋ณ๊ฒฝ ํจ์ search๊ฐ onSearch props๋ก ์ ๋ฌ๋์ด์ผ ํฉ๋๋ค
- ์ํ ๋ณ๊ฒฝ ํจ์ search๋ Search ์ปดํฌ๋ํธ์ ๊ฒ์ ๋ฒํผ ํด๋ฆญ ์ ์คํ๋์ด์ผ ํฉ๋๋ค
์ด ๋, ์๊ฐํด์ผํ๋ ๋ถ๋ถ
Parent Component -> main
A Component -> search
search ์ปดํฌ๋ํธ๊ฐ ์์์ธ๋ฐ ๋ถ๋ชจํํ ์ด๋ป๊ฒ props๋ฅผ ์ ๋ฌํ์ง? ๋ถ๋ช ๋ถ๋ชจ์์ ์ ๋ฌํ๋ค๊ณ ํ๋๋ฐ,,,
๐๐ป๐๐ป๐๐ป ์ด๋ฅผ ์ํ ๋์ด์ฌ๋ฆฌ๊ธฐ
์ฌ์ค์, search ํจ์์ ๋ชจ๋ ๊ฒ์๊ธฐ๋ฅ์ด ๋ค์ด์์ด์ผํ๊ธฐ ๋๋ฌธ์ ๋๋ถ๋ถ์ด ์ํ๋ค์ด
search ํจ์์ ์ ์๋์ด์๋ค ๊ทธ๋ฌ๋ฏ๋ก ์ํ ๋์ด์ฌ๋ฆฌ๊ธฐ๋ก main์ผ๋ก ์ ๋ฌํด์ฃผ์ด์ผ ํ๋ค.
Search.js
import { useState } from 'react'; {/* Search ์ปดํฌ๋ํธ์ onSearch๋ผ๋ props๋ก searchํจ์๋ฅผ ์ ๋ฌํ๋ค*/} function Search({onSearch}) { const [textDestination, setTextDestination] = useState('');
Main.js
return ( <div> <Head> <title>States Airline</title> <link rel="icon" href="/favicon.ico" /> </Head> <main> <h1>์ฌํ๊ฐ๊ณ ์ถ์ ๋, States Airline</h1> <Search onSearch={search}/> // ์ํ ๋์ด์ฌ๋ฆฌ๊ธฐ๋ก props๋ฅผ ์ ๋ฌ <div className="table"> <div className="row-header"> <div className="col">์ถ๋ฐ</div> <div className="col">๋์ฐฉ</div> ...(์๋ต)
Part 2 - Test
- ๊ฒ์ ์กฐ๊ฑด์ด ๋ฐ๋ ๋๋ง๋ค, FlightDataApi์ getFlight๋ฅผ ๊ฒ์ ์กฐ๊ฑด๊ณผ ํจ๊ป ์์ฒญํด์ผ ํฉ๋๋ค
- getFlight์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์, flightList ์ํ๋ฅผ ์ ๋ฐ์ดํธํด์ผ ํฉ๋๋ค
๊ฒ์ ์กฐ๊ฑด์ด ๋ฐ๋๋ค๋ ๊ฒ์ -> ์ํ๊ฐ ๋ณํ๋ค๋ ๊ฒ
sideEffect ์ฒ๋ฆฌ, side effect๋ฅผ ์คํํ๊ธฐ ์ํด์ useEffect๋ฅผ ์ฌ์ฉํ๋ค
getFilght ๊ฒฐ๊ณผ๋ ๋ฐ์ ๊ฐ์ด ์ ๋ฐ์ดํธ
// TODO: Effeck Hook์ ์ด์ฉํด AJAX ์์ฒญ์ ๋ณด๋ด๋ณด์ธ์. // TODO: ๋๋ถ์ด, ๋คํธ์ํฌ ์์ฒญ์ด ์งํ๋จ์ ๋ณด์ฌ์ฃผ๋ ๋ก๋ฉ ์ปดํฌ๋ํธ(<LoadingIndicator/>)๋ฅผ ์ ๊ณตํด๋ณด์ธ์. // useEffect(() => { useEffect(() => { getFlight(condition) }, [condition] )
- getFlight ์์ฒญ์ด ๋ค์ ๋๋ฆฌ๋ฏ๋ก, ๋ก๋ฉ ์ํ์ ๋ฐ๋ผ LoadingIndicator ์ปดํฌ๋ํธ๋ฅผ ํ์ํด์ผ ํฉ๋๋ค
์ธ๋ถ API๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ ์์ด ๋๋ฆฐ ๊ฒฝ์ฐ๊ฐ ์๊ธฐ์ ๋ก๋ฉํ๋ฉด ๊ตฌํ์ ํ์๋ค
loading state ์ฒ๋ฆฌ ์ด๊ธฐ๊ฐ์ ๋ก๋ฉ์ค์ด ์๋๊ธฐ ๋๋ฌธ์ false๋ฅผ ์ฃผ์ด์ผํ๋ค.
// TODO: Effeck Hook์ ์ด์ฉํด AJAX ์์ฒญ์ ๋ณด๋ด๋ณด์ธ์. // TODO: ๋๋ถ์ด, ๋คํธ์ํฌ ์์ฒญ์ด ์งํ๋จ์ ๋ณด์ฌ์ฃผ๋ ๋ก๋ฉ ์ปดํฌ๋ํธ(<LoadingIndicator/>)๋ฅผ ์ ๊ณตํด๋ณด์ธ์. const [isLoading, setIsLoading] = useState(false) // useEffect(() => { useEffect(() => { getFlight(condition) }, [condition] )
<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> //์ด์ api๋ฅผ ์ด์ฉํด์ list๋ฅผ ๋ฐ์ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ filterByCondition๋ ์ฃผ์ ์ฒ๋ฆฌ ํด์ค๋ค {/* <FlightList list={flightList.filter(filterByCondition)} /> */} // ๋ก๋ฉ์ค์ด๋ฉด LoadingIndicator ์ปดํฌ๋ํธ, ๋ก๋ฉ์ค์ด ์๋๋ฉด flightList ์ปดํฌ๋ํธ ์ถ๋ ฅ {isLoading ? <LoadingIndicator /> : <FlightList list ={flightList } /> } </div>
๋ก๋ฉํ๋ฉด์ด ๋์๊ฐ์ ์๋๋ก useEffect์ ์ถ๊ฐ ๊ตฌํ
useEffect(() => { setIsLoading(true); // getFlight๊ฐ ์คํ ๋๊ธฐ ์ ๋ก๋ฉํ๋ฉด getFlight(condition) .then((filter) => { setFlightList(filter) setIsLoading(false) // getFlight๊ฐ ์คํ ๋๊ธฐ ํ ๋ก๋ฉํ๋ฉด }) }, [condition] )
- ๊ฒ์ ์กฐ๊ฑด๊ณผ ํจ๊ป StatesAirline ์๋ฒ์์ ํญ๊ณตํธ ์ ๋ณด๋ฅผ ์์ฒญ(fetch)ํฉ๋๋ค
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 ํธ์ถ๋ก ๋์ฒดํ์ธ์. // fetch ๋ฅผ ์ฌ์ฉํด ๋ค์ ์์ฑํ๋ค // fetch๋ฅผ ์ด์ฉํด ์๋ฒ์ AJAX ์์ฒญ let emString = '' if(filterBy.departure){ emString = emString + `departure=${filterBy.departure}&` } if(filterBy.destination){ emString = emString + `destination=${filterBy.destination}` } let endpoint = `http://ec2-13-124-90-231.ap-northeast-2.compute.amazonaws.com:81/flight?${emString}` return fetch(endpoint) .then(res => res.json()) }
์ฌ์ค ์ด ๋ถ๋ถ์ ๋๋ ์ ํํ๊ฒ๋ ๋จธ๋ฅด๊ฒ ๋น...ใ
๋ฐ์ํ'codeStates front-end > React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[React] UI ๋์์ธ (0) 2023.02.15 [React] UI/UX (0) 2023.02.15 [React] Effect Hook (0) 2023.02.02 [React] ๋ฐ์ดํฐ ํ๋ฆ (0) 2023.02.02 [React] ์ค์ต - React Twittler State & Props (0) 2023.01.30