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.js
과 CounterListContainer.js
컴포넌트에서도 ./actions
대신에 ./modules
를불러오세요.
src/containers/App.js
src/containers/CounterListContainer.js
import * as actions from '../modules';
자, 이제 카운터가 정상적으로 작동하는지 확인하세요.