4-3. 적용하기

자, 이제 우리가 배웠던것들을 우리의 프로젝트에 적용을 해봅시다.

모듈 작성

우선, redux-actions 를 설치하세요.

yarn add redux-actions

그 다음, src 디렉토리에 modules 디렉토리를 만들고, 그 안에 index.js 파일을 생성하세요.

src/modules/index.js

먼저, redux-actions 에서 createAction 과 handleActions 를 불러오고 액션타입을 선언하도록 하겠습니다.

추후 immutable 의 Map 과 List 도 필요해질테니 미리 불러오겠습니다.

import { createAction, handleActions } from 'redux-actions';
import { Map, List } from 'immutable';

// 액션 타입 
const CREATE = 'counter/CREATE';
const REMOVE = 'counter/REMOVE';
const INCREMENT = 'counter/INCREMENT';
const DECREMENT = 'counter/DECREMENT';
const SET_COLOR = 'counter/SET_COLOR';

이제 방금 만든 액션타입들을 가지고 createAction 을 통하여 액션생성자들을 만들겠습니다. 이 액션생성자들은 전부 밖으로 내보내주어야 하니 export키워드를 사용하세요.

// 액션 생성자
export const create = createAction(CREATE); // color
export const remove = createAction(REMOVE); 
export const increment = createAction(INCREMENT); // index
export const decrement = createAction(DECREMENT); // index
export const setColor = createAction(SET_COLOR); // { index, color }

해당 액션생성자들이, 어떤 파라미터를 받아야하는지, 주석에 메모로 달아둡니다.

다음, 초기상태를 리듀서 파일에서 복사해오세요.

// 초기 상태를 정의합니다
const initialState = Map({
    counters: List([
        Map({
            color: 'black',
            number: 0
        })
    ])
});

그리고, handleActions 를 통하여 리듀서의 틀을 만들어주겠습니다.

export default handleActions({
    [CREATE]: (state, action) => state,
    [REMOVE]: (state, action) => state,
    [INCREMENT]: (state, action) => state,
    [DECREMENT]: (state, action) => state,
    [SET_COLOR]: (state, action) => state,
}, initialState);

우리의 액션타입에는 접두사가 들어가있기 때문에 그냥 CREATE: 를 하면 안되고, [CREATE]: 로 해주어야합니다.

그 다음에는, 기존에 작성했던 리듀서를 참조하여 하나하나 구현해보세요. SET_COLOR 을 제외한 액션들에서는 파라미터들의 이름이 payload 로 통합되었습니다.

SET_COLOR 의 경우엔 index 와 color 값이 payload 객체 안에 들어가있기에 action.payload.index 이런식으로 작성을 해야하구요

그리고 이전 리듀서에서는 switch 를 사용했기에 counters 라는 공유되는 변수가 있었지만, 이젠 각 함수마다 counters 를 준비해주세요.

export default handleActions({
    [CREATE]: (state, action) => {
        const counters = state.get('counters');

        return state.set('counters', counters.push(
            Map({
                color: action.payload,
                number: 0
            })
        ))
    },

    [REMOVE]: (state, action) => {
        const counters = state.get('counters');

        return state.set('counters', counters.pop())
    },

    [INCREMENT]: (state, action) => {
        const counters = state.get('counters');

        return state.set('counters', counters.update(
            action.payload, 
            (counter) => counter.set('number', counter.get('number') + 1))
        );
    },

    [DECREMENT]: (state, action) => {
        const counters = state.get('counters');

        return state.set('counters', counters.update(
            action.payload, 
            (counter) => counter.set('number', counter.get('number') - 1))
        );
    },

    [SET_COLOR]: (state, action) => {
        const counters = state.get('counters');

        return state.set('counters', counters.update(
            action.payload.index, 
            (counter) => counter.set('color', action.payload.color))
        );
    },
}, initialState);

변화 반영

이제 actions, reducers 디렉토리는 쓸모없어졌으니 삭제하세요.

그리고, src 디렉토리의 index.js 에서, ./reducers 파일을 불러오는 대신에 ./modules 를 불러오세요

src/index.js

import reducers from './modules';

다음, App.jsCounterListContainer.js 컴포넌트에서도 ./actions 대신에 ./modules 를불러오세요.

src/containers/App.js

src/containers/CounterListContainer.js

import * as actions from '../modules';

자, 이제 카운터가 정상적으로 작동하는지 확인하세요.

results matching ""

    No results matching ""