diff --git a/babel-plugin-macros.config.js b/babel-plugin-macros.config.js new file mode 100644 index 0000000..21aa879 --- /dev/null +++ b/babel-plugin-macros.config.js @@ -0,0 +1,8 @@ +const isDev = process.env.NODE_ENV !== 'production'; + +module.exports = { + styledComponents: { + fileName: isDev, + displayName: isDev, + }, +}; diff --git a/src/APIs/index.js b/src/APIs/index.js new file mode 100644 index 0000000..aca05c9 --- /dev/null +++ b/src/APIs/index.js @@ -0,0 +1,7 @@ +import axios from 'axios'; + +export default { + getBeerList: () => { + return axios.get(`https://api.punkapi.com/v2/beers`); + }, +}; diff --git a/src/Components/Nav.js b/src/Components/Nav.js index 390c230..640cf78 100644 --- a/src/Components/Nav.js +++ b/src/Components/Nav.js @@ -18,7 +18,6 @@ const Nav = () => { return (
- {/*
*/} {Object.entries(menuList).map(([menuName, path]) => ( { + const [isFetched, setIsFetched] = useState(false); + const [data, setData] = useState(null); + const [error, setError] = useState(null); + + useEffect(() => { + callback() + .then(res => { + setData(res.data); + setIsFetched(true); + }) + .catch(err => { + setError(err); + }); + }, [callback]); + + return [isFetched, data, error]; +}; + +export default useFetchData; diff --git a/src/Modules/beerList.js b/src/Modules/beerList.js new file mode 100644 index 0000000..43f48bd --- /dev/null +++ b/src/Modules/beerList.js @@ -0,0 +1,47 @@ +const initialState = { + loading: false, + data: null, + error: null, +}; + +export const GET_BEER_LIST_REQUEST = 'beerlist/GET_BEER_LIST_REQUEST'; +export const GET_BEER_LIST_SUCCESS = 'beerlist/GET_BEER_LIST_SUCCESS'; +export const GET_BEER_LIST_FAILED = 'beerlist/GET_BEER_LIST_FAILED'; + +export const getBeerListRequest = () => ({ + type: GET_BEER_LIST_REQUEST, +}); +export const getBeerListSuccess = payload => ({ + type: GET_BEER_LIST_SUCCESS, + payload, +}); +export const getBeerListFailed = payload => ({ + type: GET_BEER_LIST_FAILED, + payload, +}); + +const beerListReducer = (state = initialState, action) => { + switch (action.type) { + case GET_BEER_LIST_REQUEST: + return { + ...state, + loading: true, + }; + case GET_BEER_LIST_SUCCESS: + return { + ...state, + loading: false, + data: action.payload, + }; + case GET_BEER_LIST_FAILED: + return { + ...state, + loading: false, + error: action.payload, + }; + default: + return state; + } +}; + +export default beerListReducer; diff --git a/src/Modules/index.js b/src/Modules/index.js index 62720e3..be81ec7 100644 --- a/src/Modules/index.js +++ b/src/Modules/index.js @@ -4,15 +4,17 @@ import { all } from 'redux-saga/effects'; // watcher saga -> actions -> worker saga // import loading from "./loading"; import { enableES5 } from 'immer'; +import beerListReducer from './beerList'; +import getBeerListSaga from './saga/beerListSaga'; enableES5(); -const rootReducer = combineReducers({}); +const rootReducer = combineReducers({ beerListReducer }); // export default rootReducer; export default rootReducer; // wathcer saga export function* rootSaga() { - yield all([]); + yield all([getBeerListSaga()]); } diff --git a/src/Modules/saga/beerListSaga.js b/src/Modules/saga/beerListSaga.js new file mode 100644 index 0000000..9b34d92 --- /dev/null +++ b/src/Modules/saga/beerListSaga.js @@ -0,0 +1,21 @@ +import { call, put, takeLatest } from 'redux-saga/effects'; +import { + GET_BEER_LIST_REQUEST, + getBeerListSuccess, + getBeerListFailed, +} from '../beerList'; +import APIs from '../../APIs'; + +function* getBeerList() { + try { + const { data } = yield call(APIs.getBeerList); // yield call은 결과 반환시까지 기다려줌 + yield put(getBeerListSuccess(data)); // action dispatch + } catch (err) { + yield put(getBeerListFailed(err)); + } +} +export default function* getBeerListSaga() { + yield takeLatest(GET_BEER_LIST_REQUEST, getBeerList); + // yield takeLatest(...) : 가장 마지막 요청에 대해 어떤 함수를 실행시킬지 지정 + // REQUEST_DATA 액션 객체가 들어오면 getApiData 실행 +} diff --git a/src/Pages/Beers.js b/src/Pages/BeerList.js similarity index 68% rename from src/Pages/Beers.js rename to src/Pages/BeerList.js index 97994ac..3e8a81e 100644 --- a/src/Pages/Beers.js +++ b/src/Pages/BeerList.js @@ -1,8 +1,8 @@ import React from 'react'; import styled from 'styled-components/macro'; -const Beers = () => { +const BeerList = () => { return

Beer List

; }; -export default Beers; +export default BeerList; diff --git a/src/Pages/Cart.js b/src/Pages/CartList.js similarity index 100% rename from src/Pages/Cart.js rename to src/Pages/CartList.js diff --git a/src/Pages/Home.js b/src/Pages/Home.js index 20c0a19..5caff85 100644 --- a/src/Pages/Home.js +++ b/src/Pages/Home.js @@ -1,8 +1,11 @@ import React from 'react'; +import { useSelector } from 'react-redux'; import styled from 'styled-components/macro'; const Home = () => { - return

Home

; + const beerList = useSelector(s => s.beerListReducer.data); + + return

{`저장된 맥주 정보 ${beerList?.length || 0}개`}

; }; export default Home; diff --git a/src/Routes.js b/src/Routes.js index 2b7512a..f5a0905 100644 --- a/src/Routes.js +++ b/src/Routes.js @@ -1,4 +1,5 @@ -import React from 'react'; +import React, { useEffect } from 'react'; +import { useDispatch } from 'react-redux'; import { BrowserRouter as Router, Route, @@ -7,18 +8,25 @@ import { } from 'react-router-dom'; import Nav from './Components/Nav'; import Home from './Pages/Home'; -import Beers from './Pages/Beers'; -import Cart from './Pages/Cart'; +import BeerList from './Pages/BeerList'; +import CartList from './Pages/CartList'; +import { getBeerListRequest } from './Modules/beerList'; const Routes = () => { + const dispatch = useDispatch(); + + useEffect(() => { + dispatch(getBeerListRequest()); + }, [dispatch]); + return (