4-2. redux-actions 를 통한 더 쉬운 액션관리
redux-actions
패키지에는 리덕스의 액션들을 관리하기 위한 유용한 createAction
과 handleActions
가 있습니다. 이번 섹션에서는 이 함수들이 어떤 기능을하는지 알아보도록 하겠습니다.
createAction 을 통한 액션생성 자동화
리덕스에서, 액션을 만들다보면 드는 의문이, 이걸 굳이 하나하나 액션 생성자를 만들어야하나? 입니다.
예를 들어, 우리가 기존에 만들었던 increment
와 decrement
코드를 다시 한번 읽어봅시다.
export const increment = (index) => ({
type: types.INCREMENT,
index
});
export const decrement = (index) => ({
type: types.DECREMENT,
index
});
그냥 파라미터로 전달받은 값을 객체에 넣어주는것 뿐인데 이걸 자동화할수도 있지 않을까요?
createAction
을 사용한다면 위 작업을 다음과 같이 자동화 시켜 줄 수 있습니다.
export const increment = createAction(types.INCREMENT);
export const decrement = createAction(types.DECREMENT);
하지만, 이런식으로 하면 그 파라미터의 값이 index
가 될 지 뭐가 될 지 모릅니다. 그렇기 때문에, 파라미터로 전달받은 값을 액션의 payload
값으로 설정해줍니다. 따라서 increment(3)
가 실행된다면, 다음과 같이 객체를 만들어주겠죠.
{
type: 'INCREMENT',
payload: 5
}
setColor의 경우엔 어떨까요?
export const setColor = createAction(types.SET_COLOR);
setColor({index: 5, color: '#fff'})
/* 결과:
{
type: 'SET_COLOR',
payload: {
index: 5,
color: '#fff'
}
}
*/
어때요? 이해가 가나요? 액션이 갖고있을 수 있는 변수를 payload
로 통일하므로서, 액션을 생성하는것을 자동화 할 수 있게 되는 것이지요. 편리하지만, 단점으로는 코드를 봤을때 해당 액션생성자가 파라미터로 필요한 값이 뭔지 모르기때문에, 그 위에 주석을 작성해주어야 합니다.
switch 문 대신 handleActions 사용하기
리듀서에서 액션의 type 에 따라 다른 작업을 하기 위해서 우리는 switch
문을 사용했지요. 하지만 이 방식엔 아주 중요한 결점이 한가지 있습니다. 바로, scope
가 리듀서 함수로 설정되어있다는것이지요.
그렇기 때문에 서로 다른 case
에서 let
이나 const
를 통하여 변수를 선언하려고 하다보면 같은 이름이 중첩될시엔 에러가 발생합니다.
그렇다고해서 각 case
마다 함수를 정의하는건 코드를 읽기 힘들어질것이구요..
이 문제를 해결해주는것이 바로 handleActions
입니다. 이 함수를 사용하면 다음과 같은 방식으로 해결 할 수 있습니다.
const reducer = handleActions({
INCREMENT: (state, action) => ({
counter: state.counter + action.payload
}),
DECREMENT: (state, action) => ({
counter: state.counter - action.payload
})
}, { counter: 0 });
첫번째 파라미터로는 액션에 따라 실행 할 함수들을 가지고있는 객체, 두번째 파라미터로는 상태의 기본 값 (initialState) 를 넣어주면 됩니다.
한번, 직접 사용해보고싶지 않나요? 이제, 방금 배운 Duck 구조와 redux-actions 을 저희 카운터에 적용을 해보겠습니다.