마지막에 한 것처럼, 우리는 이제 최상위 앱 리듀서에 대한 "상태의 조각"의 로직을 처리하기 위해 리덕스에서 제공하는 combineReducers 유틸리티를 사용할 수 있습니다. 이것이 최종결과물입니다.
// 재사용 가능한 유틸리티 함수functionupdateObject(oldObject, newValues) {// 새로운 객체를 첫번째 매개변수로 전달한다는 아이디어를 캡슐화// 데이터를 변경하는 대신에 데이터를 확실히 복사하기 위해 Object.assign을 사용합니다.returnObject.assign({}, oldObject, newValues);}functionupdateItemInArray(array, itemId, updateItemCallback) {constupdatedItems=array.map(item => {if(item.id !== itemId) {// 한가지 항목만 업데이트하기 때문에 다른 항목은 유지합니다.return item; }// 업데이트 된 항목을 만들기 위해 주어진 콜백을 사용합니다.constupdatedItem=updateItemCallback(item);return updatedItem; });return updatedItems;}functioncreateReducer(initialState, handlers) {returnfunctionreducer(state = initialState, action) {if (handlers.hasOwnProperty(action.type)) {return handlers[action.type](state, action) } else {return state } }}// 특정 케이스의 핸들러 ("케이스 리듀서")functionsetVisibilityFilter(visibilityState, action) {// 기술적으로, 우리는 이전의 상태에 대해서도 신경쓰지 않습니다.returnaction.filter;}// 전체 상태의 조각에 대한 핸들러("슬라이스 리듀서")constvisibilityReducer=createReducer('SHOW_ALL', {'SET_VISIBILITY_FILTER': setVisibilityFilter});// 케이스 리듀서functionaddTodo(todosState, action) {constnewTodos=todosState.concat({ id:action.id, text:action.text, completed:false });return newTodos;}// 케이스 리듀서functiontoggleTodo(todosState, action) {constnewTodos=updateItemInArray(todosState,action.id, todo => {returnupdateObject(todo, {completed :!todo.completed}); });return newTodos;}// 케이스 리듀서functioneditTodo(todosState, action) {constnewTodos=updateItemInArray(todosState,action.id, todo => {returnupdateObject(todo, {text :action.text}); });return newTodos;}// 슬라이스 리듀서consttodosReducer=createReducer([], {'ADD_TODO': addTodo,'TOGGLE_TODO': toggleTodo,'EDIT_TODO': editTodo});// "루트 리듀서"constappReducer=combineReducers({ visibilityFilter : visibilityReducer, todos : todosReducer});
우리는 리듀서를 나누는 몇 가지 함수를 살펴봤습니다: updateObject, createReducer같은 헬퍼 유틸리티, setVisibilityFilter, addTodo같은 케이스에 대한 핸들러, visibilityReducer, todosReducer같은 부분상태 핸들러. 또한 appReducer는 "루트 리듀서"의 예입니다.
이 예제에서의 결과물은 처음보다 현저히 깁니다. 이는 유틸리티 함수를 추출했고, 명확성을 위해 분리된 명령문을 반환하는 것과 같은 방법으로 일부러 장황하게 작성했기 때문입니다. 함수를 개별적으로 보면 각각의 책임이 줄어들었고 의도가 명확해졌습니다. 또한 실제 애플리케이션에서는 아마 reducerUtilities.js, visibilityReducer.js, todosReducer.js, rootReducer.js과 같이 파일로 분리될 겁니다.