본문 바로가기

redux

리덕스_8_리스트 조회하기

망고플레이트를 예시로 사용해봅니다.

https://www.mangoplate.com/

 

망고플레이트: 나만의 맛집 검색

솔직하고 거짓없는 리뷰로 나만의 맛집을 쉽고 빠르게 찾아보세요!

www.mangoplate.com

1. 새 프로젝트를 만든다.

  package.json에 아래있는 것들을 추가한다.

"express": "^4.17.1",
"mongodb": "^3.5.8",
"redux": "^4.0.5",
"react-redux": "^7.2.0",
"react-router": "^5.2.0",                        //페이지 넘길 때 사용
"react-router-dom": "^5.2.0",
"redux-logger": "^3.0.6"                        //log 표시 할 떄 사용
"redux-thunk": "^2.3.0"                         //비동기일 때 사용
"axios": "^0.19.2"                                 //서버 연결시 사용

2. src안에 폴더를 4개 넣는다.

   1. components

   2. atcions

   3. reducers

   4. store

3. action 폴더에 types이라는 이름의 javascript파일을 하나 만든다. 

  액션을 등록할 때에는 변수로 등록을 해야한다.

   그래서 const로 변수를 만들어준다. 

//액션: 구분하는 문자열 저장
export  const FETCH_CATEGORY ='FETCH_CATEGORY'
export  const FETCH_CATE_FOOD ='FETCH_CATE_FOOD'
export  const FETCH_FOOD_DETAIL ='FETCH_FOOD_DETAIL'

카테고리를 가져오는 것, 음식정보 가져오는 것, 자세한 음식정보 가져오는 것

총 3개의 STATE가 생성되었다고 보면 된다.

 

4. reducer에 foodReducer라는 이름의 javascript파일을 하나 만든다. 

  store에 store라는 이름의 javascript파일을 하나 만든다. (저장공간용)

 

foodReducer에 types에 적어놓은 애들을 import해주거 초기값을 만들어준다. ,

import {FETCH_CATEGORY,FETCH_CATE_FOOD,FETCH_FOOD_DETAIL} from "../actions/types";

const initialState ={
    category:[],
    cafe_food:[],
    food_detail:{}
}

초기값과 action을 받는 function을 만든다.

switch문으로 FETCH_CATEGORY일때 FETCH_CATE_FOOD일때 FETCH_FOOD_DETAIL일때의 경우를 쓴다.

export default function (state=initialState, action) {
    switch (action.type) {
        case FETCH_CATEGORY:
            return{
                ...state,
                category: action.payload
            }
        case FETCH_CATE_FOOD:
            return {
                ...state,
                cafe_food: action.payload
            }
        case FETCH_FOOD_DETAIL:
            return {
                ...state,
                food_detail: action.payload
            }
        default:
            return state
    }
}

...state는 생략하는 것이 아니라 전에 있는 것을 가져오는 것이다.

 

+) 값을 보내는 dispatch는 이런식으로 쓴다. 

dispatch({
        type: FETCH_CATEGORY   //카테고리의 function을 달라는 것 
        payLoad: data(category) //카테고리에 해당되는 데이터 보내기 
    })

5. reducer에 index.js.도 만든다. reduce가 여러개 일 때 하나로 모아주는 역할을 한다. 

index에 combineReducers 를 import한다. 얘가 묶어 줄 때 사용하는 함수이다. 

import {combineReducers} from "redux";
import foodReducer from "./foodReducer";

export default combineReducers({
    food: foodReducer
})

recipe도 있으면 food: foodReducer 밑에 쓰면 된다. 

 

6. 이렇게 만든 것들은 store에서 관리한다. 그래서 store.js로 이동한다.

   **rootReducer는 index.js를 의미한다.

import rootReducer from './reducers'
import {createLogger} from "redux-logger/src";
import thunk from "redux-thunk";

//미들웨어

//logger 생성
const logger = createLogger();

//thunk 생성(비동기프로그램)
const initialState={}
const middleware=[thunk,logger];

createStore로 스토어를 하나 만들어준다.

const store = createStore(
    rootReducer,
    initialState,
    compose()
)

compose는 합성시켜주는 역할을 한다. (어떻게 변경되는지 모니터링이 필요해서 넣은 것. 없어도 된다.)

안에 미드웨어와 window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() 이걸 넣어준다. 

    compose(applyMiddleware(...middleware),
        window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    )

store 전체 코드)

import rootReducer from "../reducers"
import {createLogger} from "redux-logger/src";
import thunk from "redux-thunk";
import {applyMiddleware, compose, createStore} from "redux";

//미들웨어

//logger 생성
const logger = createLogger();

//thunk 생성(비동기프로그램)
const initialState={}
const middleware=[thunk,logger];

const store = createStore(
    rootReducer,
    initialState,
    compose(applyMiddleware(...middleware),
        window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    )
)

export default store;

7. components에 js를 세개 만든다.

8. 서버 연결을 위해 food-server를 만든다.

const express=require("express")
const app=express();

app.listen(3355,()=>{
    console.log("Server Start...","http://localhost:3355")
})

app.all('/*', function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    next();
});

const Client=require("mongodb").MongoClient;

app.get('/category',(request,response)=>{


    var url="mongodb://211.238.142.181:27017";//몽고디비 주소
    Client.connect(url,(err,client)=>{
        var db=client.db('mydb');
        db.collection('category').find({})
            .toArray((err,docs)=>{
                // 요청한 사용자 => 데이터 전송
                response.json(docs);
                console.log(docs)
                client.close();
            })
    })
})

9. index.html에 css를 넣는다.

10. components에 있는 Category.js에 function을 만든다.

useDispatch를 import 해주어야 foodReducer.js에 있는 case문에서 action할 수 있다.

import React,{useEffect} from "react";
import {FETCH_CATEGORY} from "../actions/types";
import {useDispatch,useSelector} from "react-redux";
import axios from 'axios'

export default function Category(props) {
    const dispatch=useDispatch(); //reducer 함수를 호출
    useEffect(()=>{
        axios.get('http://localhost:3355/category').then((result)=>{
            dispatch({
                type:FETCH_CATEGORY,
                payload:result.data
            })
        })
    },[])

    //state 갱신   => store에서 변경된 state를 읽어온다.
    const category_data = useSelector((state)=>state.foods.category)

    const html = category_data.map((m)=>
        <div className="col-md-4">
            <div className="thumbnail">
                <img src={m.poster} alt="Lights" style={{"width": "100%"}}/>
                <div className="caption">
                    <p>{m.title} </p>
                </div>
            </div>
        </div>
    )
    return(
        <div className={"row"}>
            {html}
        </div>
    )

}

11. category를 클릭하면 넘어가야 하니깐 다른 페이지들도 해준다. 

CateFood에 이렇게 대충 코딩한다.

import React from "react";

function CateFood(props) {
    return(
        <div className={"row"}>

        </div>
    )
}

export default CateFood

FoodDetail.js에도 똑같이 넣어준다. 이렇게 해야 오류가 생기지 않는다. 

import React from "react";

function FoodDetail(props) {
    return(
        <div className={"row"}>

        </div>
    )
}

export default FoodDetail

12. App.js에서 최종 동작하므로 이걸 수정해준다.

import React from 'react';
import {BrowserRouter as Router,Route, Switch} from "react-router-dom";
import Category from "./components/Category";
import CateFood from "./components/CateFood";
import FoodDetail from "./components/FoodDetail";
import store from "./store/store";
import {Provider} from 'react-redux'

function App() {
  return (
      <Provider store={store}>
      <Router>
        <switch>
          <Route exact path={"/"} component={Category}/>
          <Route path={"/cate_food"} component={CateFood}/>
          <Route path={"/food_detail"} component={FoodDetail}/>
        </switch>
      </Router>
      </Provider>
  );
}

export default App;

반응형

'redux' 카테고리의 다른 글

리덕스_10_게시글 상세내역 보기  (0) 2020.06.06
리덕스_9_게시글 내용 보기  (0) 2020.06.06
리덕스는 무엇일까?  (0) 2020.06.06
리덕스 _ 환경설정  (0) 2020.05.23