1-10. 서브 리듀서 만들기
우리의 첫 리덕스 프로젝트는 끝이 났지만 아직 공부는 끝나지 않았습니다. 기존 리듀서를 색상 리듀서, 그리고 숫자 리듀서로 분리를 시킨다음에, combineReducers
를 통해 이를 합쳐서 루트 리듀서로 만드는 방법을 알아보겠습니다.
우선, reducers
디렉토리에 color.js
와 number.js
파일을 다음과 같이 만드세요.
src/reducers/color.js
import * as types from '../actions/ActionTypes';
const initialState = {
color: 'black'
};
const color = (state = initialState, action) => {
switch(action.type) {
case types.SET_COLOR:
return {
color: action.color
};
default:
return state;
}
}
export default color;
src/reducers/number.js
import * as types from '../actions/ActionTypes';
const initialState = {
number: 0
};
const number = (state = initialState, action) => {
switch(action.type) {
case types.INCREMENT:
return {
number: state.number + 1
};
case types.DECREMENT:
return {
number: state.number - 1
};
default:
return state;
}
}
export default number;
그 다음에, reducers
디렉토리의 index.js
에서 redux 의 combineReducers
를 불러온뒤 다음과 같이 호출하세요.
src/reducers/index.js
import number from './number';
import color from './color';
import { combineReducers } from 'redux';
/*
서브 리듀서들을 하나로 합칩니다.
combineReducers 를 실행하고 나면, 나중에 store의 형태가 파라미터로 전달한 객체의 모양대로 만들어집니다.
지금의 경우:
{
numberData: {
number: 0
},
colorData: {
color: 'black'
}
}
로 만들어집니다.
*/
const reducers = combineReducers({
numberData: number,
colorData: color
});
export default reducers;
combineReducers
는 여러개의 서브리듀서를 하나로 합쳐줍니다. 이 과정에서 함수에 객체를 전달하게 되는데, 이 객체의 구조에 따라 합쳐진 리듀서의 상태의 구조가 만들어집니다.
따라서, 지금의 구조대로라면 기존 프로젝트가 작동하지 않겠죠?
그럼, ContactContainer
컴포넌트의 mapStateToProps
함수를 조금 수정해줍시다:
src/containers/ContactContainer.js
import Counter from '../components/Counter';
import * as actions from '../actions';
import { connect } from 'react-redux';
import { getRandomColor } from '../utils';
// store 안의 state 값을 props 로 연결해줍니다.
const mapStateToProps = (state) => ({
color: state.colorData.color,
number: state.numberData.number
});
/*
액션 생성자를 사용하여 액션을 생성하고,
해당 액션을 dispatch 하는 함수를 만들은 후, 이를 props 로 연결해줍니다.
*/
const mapDispatchToProps = (dispatch) => ({
onIncrement: () => dispatch(actions.increment()),
onDecrement: () => dispatch(actions.decrement()),
onSetColor: () => {
const color = getRandomColor();
dispatch(actions.setColor(color));
}
});
// Counter 컴포넌트의 Container 컴포넌트
// Counter 컴포넌트를 어플리케이션의 데이터 레이어와 묶는 역할을 합니다.
const CounterContainer = connect(
mapStateToProps,
mapDispatchToProps
)(Counter);
export default CounterContainer;
자, 리듀서를 분리하는 연습도 마쳤습니다.
이제, 2장으로 넘어가서 조금 더 복잡한 상태를 관리해봅시다!
지금까지 작성한 코드는 https://github.com/vlpt-playground/redux-counter/tree/single-counter 에서 열람 할 수 있습니다.