sliceReducerA가 sliceReducerB의 상태 조각이 필요하거나, sliceReducerB가 전체 상태 트리를 인자로 필요로 한다면,
위 요구사항은 combineReducer가 처리하지 못한다. 추가 인자로 필요한 데이터를 전달할 수 있는 custom function을 작성하여 해결 가능하다.
function combinedReducer(state, action) {
switch (action.type) {
case 'A_TYPICAL_ACTION': {
return {
a: sliceReducerA(state.a, action),
b: sliceReducerB(state.b, action)
};
}
case 'SOME_SPECIAL_ACTION': {
return {
// specifically pass state.b as an additional argument
a: sliceReducerA(state.a, action, state.b),
b: sliceReducerB(state.b, action)
};
}
case 'ANOTHER_SPECIAL_ACTION': {
return {
a: sliceReducerA(state.a, action),
// specifically pass the entire state as an additional argument
b: sliceReducerB(state.b, action, state)
};
}
default:
return state;
}
}
thunk function or saga function or 비슷한 접근방식으로 쉽게 해결가능.
function someSpecialActionCreator() {
return (dispatch, getState) => {
const state = getState();
const dataFromB = selectImportantDataFromB(state);
dispatch({
type: 'SOME_SPECIAL_ACTION',
payload: {
dataFromB
}
});
};
}
위와 같이 하면 parent reducer는 1번과 같이 특별히 할게 없음. 제일 간단한 해결 방ㅇ법.
각 slice reducer는 독립적으로 업데이트할 수 있다. 또한, "special" case를 처리하기위한 다른 리듀서를 사용할 수 있다. 래핑된 함수는 final result를 생성하기 위해 다른 리듀서를 호출한다.
const combinedReducer = combineReducers({
a: sliceReducerA,
b: sliceReducerB
});
function crossSliceReducer(state, action) {
switch (action.type) {
case 'SOME_SPECIAL_ACTION': {
return {
// specifically pass state.b as an additional argument
a: handleSpecialCaseForA(state.a, action, state.b),
b: sliceReducerB(state.b, action)
};
}
default:
return state;
}
}
function rootReducer(state, action) {
const intermediateState = combinedReducer(state, action);
const finalState = crossSliceReducer(intermediateState, action);
return finalState;
}