Ming's develop story

Chapter3 - 리덕스 써보기(덕스 구조, 모듈 만들기, 스토어 만들기 및 컴포넌트 연결) 본문

스파르타코딩클럽 - 항해99/항해99 Chapter3 - react 주특기 기본

Chapter3 - 리덕스 써보기(덕스 구조, 모듈 만들기, 스토어 만들기 및 컴포넌트 연결)

Ming 2021. 11. 22. 21:19

덕스 (ducks) 구조

  • 보통 리덕스를 사용할 때는, 모양새대로 action, actionCreator, reducer를 분리해서 작성한다. (액션은 액션끼리, 액션생성함수는 액션생성함수끼리, 리듀서는 리듀서끼리 작성한다)
  • 덕스 구조는 모양새로 묶는 대신 기능으로 묶어 작성한다. (버킷리스트를 예로 들자면, 버킷리스트의 action, actionCreator, reducer를 한 파일에 넣으면 된다)
  • 덕스 구조로 리덕스 모듈을 만들어 보자!

덕스 구조를 잘 설명해 주는 사이트

헷갈릴 때 들어가서 읽어보자

 

 

모듈을 만들때 복사할 기본 코드(사이트와 동일)

// widgets.js

// Actions 타입을 정해준다
const LOAD = "my-app/widgets/LOAD"//서버에서 데이터를 가져올때 쓴다.
const CREATE = "my-app/widgets/CREATE";
const UPDATE = "my-app/widgets/UPDATE";
const REMOVE = "my-app/widgets/REMOVE";

// Reducer
export default function reducer(state = {}, action = {}) {  파라미터에 값을 할당하는 것은 기본값을 주는 것이다(오류 방지용)
  switch (action.type) {                                             액션에 혹시라도 값이 안들어오면 빈 딕셔너리라는 것을 알려준다
    // do reducer stuff
    default:
      return state;
  }
}

// Action Creators
export function loadWidgets() {
  return { type: LOAD };
}

export function createWidget(widget) {
  return { type: CREATE, widget };
}

export function updateWidget(widget) {
  return { type: UPDATE, widget };
}

export function removeWidget(widget) {
  return { type: REMOVE, widget };
}

// side effects, only as applicable
// e.g. thunks, epics, etc
// 데이터를 외부(서버 등)에서 가져와야 하는경우(비동기 통신)
// 바로 리듀서에 넘길수가 없어서 '미들웨어'로서 데이터를 가져와서 넘겨주는 중간다리 역할
export function getWidget() {
  return (dispatch) =>
    get("/widget").then((widget) => dispatch(updateWidget(widget)));
}


Tip.

//JS에서는 딕셔너리에 키, 밸류가 똑같으면 하나로 생략 가능하다.
{widget: widget} => { widget }

좌, 우측이 동일하다

src > redux > modules 경로 안에 작성

실전 적용

// bucket.js

// Actions 타입을 정해준다
const CREATE = "bucket/CREATE";
// 초깃값 지정
const initialState = {
  list: ["영화관 가기", "매일 책읽기", "수영 배우기"],
};

// Action Creators
export function createBucket(bucket) {
  return { type: CREATE, bucket }; //bucket= 추가할 값(데이터)
}

// Reducer
export default function reducer(state = { initialState }, action = {}) {
  switch (action.type) {
    case "bucket/CREATE": {
      const new_bucket_list = [...state.list, action.bucket]; // 새로운 상태값 리턴위해 만들어준다. ***
      return {list : new_bucket_list}
    }
    default:
      return state;
  }
}

*** 부분 추가설명

원래 리스트 = ...state.list

새로운 데이터 = action.bucket  액션에 작성해 둔것

이렇게 작성함으로써 새 데이터를 리턴 해준다!

 

위는 모듈을 다 만든것이고, 이런 모듈안에 있는 리듀서를 묶어서 스토어를 만들고,

컴포넌트가 스토어를 구독하도록 해야한다.

 

초깃값도 지정해주기

 

Store 만들기

경로는 src > redux안에 작성

import {createStore, combineReducers} from "redux";
import bucket from "./modules/bucket";

const rootReducer = combineReducers({bucket});

const store = createStore(rootReducer);

export default store;

정리하자면 

(리듀서를 싹 다 묶은것(rootReducer) + 필요한 옵션들)을 combineReducers로 싹 묶어서! 

createStore에 전달! 

=> store

 

2개 이상의 리듀서일 경우

Store에 컴포넌트 연결 (이것을 '컴포넌트에 스토어를 주입한다' 라고 함)

store를 다 만들었으니 이젠 컴포넌트와 연결할 차례! 

index.js에서 필요한 작업을 해줄것이다.

스토어를 불러오고 → 우리 버킷리스트에 주입하면 끝!

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { BrowserRouter } from "react-router-dom";
import { Provider } from "react-redux"// 프로바이더 import
import store from "./redux/configStore"; // 스토어 import

ReactDOM.render(
  <Provider store={store}// 프로바이더로 감싸주고 store를 불러온다!
    <BrowserRouter>
    <App />
  </BrowserRouter>
  </Provider>,
  document.getElementById("root")
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

1. Provider import 하기

2. store import 하기

3. Provider로 감싸주고 store 불러오기

Comments