이 페이지는 PageTurner AI로 번역되었습니다(베타). 프로젝트 공식 승인을 받지 않았습니다. 오류를 발견하셨나요? 문제 신고 →
combineReducers(reducers)
개요
combineReducers 헬퍼 함수는 서로 다른 "슬라이스 리듀서" 함수들을 값으로 가지는 객체를 단일 결합 리듀서 함수로 변환합니다. 이 결과물은 Redux Toolkit의 configureStore나 레거시 createStore 메서드에 전달할 수 있습니다.
생성된 결합 리듀서는 액션이 디스패치될 때마다 모든 슬라이스 리듀서를 호출하고, 그 결과를 단일 상태 객체로 집계합니다. 이를 통해 리듀서 로직을 독립적인 함수들로 분할하고 각각이 상태의 특정 부분을 관리할 수 있습니다.
이 기능은 거의 필요하지 않을 것입니다. Redux Toolkit의 configureStore 메서드는 슬라이스 리듀서 객체를 전달받으면 자동으로 combineReducers를 호출합니다:
const store = configureStore({
reducer: {
posts: postsReducer,
comments: commentsReducer
}
})
루트 리듀서를 직접 구성해야 할 경우에는 여전히 combineReducers()를 직접 호출할 수 있습니다.
상태 슬라이스
combineReducers()가 생성하는 상태는 각 리듀서의 상태를 combineReducers()에 전달된 키 아래로 네임스페이스화합니다
예시:
rootReducer = combineReducers({potato: potatoReducer, tomato: tomatoReducer})
// This would produce the following state object
{
potato: {
// ... potatoes, and other state managed by the potatoReducer ...
},
tomato: {
// ... tomatoes, and other state managed by the tomatoReducer, maybe some nice sauce? ...
}
}
전달 객체에서 리듀서에 서로 다른 키를 사용해 상태 키 이름을 제어할 수 있습니다. 예를 들어 combineReducers({ todos: myTodosReducer, counter: myCounterReducer })를 호출하면 상태 형태는 { todos, counter }가 됩니다.
인자
reducers(객체): 결합되어야 하는 서로 다른 리듀서 함수들에 대응하는 값들을 가진 객체.
combineReducers({
posts: postsReducer,
comments: commentsReducer
})
전달되는 모든 리듀서가 따라야 할 규칙은 아래 노트를 참고하세요.
반환값
(함수): reducers 객체 내부의 모든 리듀서를 호출하고 동일한 형태의 상태 객체를 구성하는 리듀서.
주의사항
이 함수는 다소 의견이 반영되어 있으며 초보자가 흔히 저지르는 실수를 방지하도록 설계되었습니다. 따라서 루트 리듀서를 직접 작성할 때는 필요 없는 몇 가지 규칙을 적용합니다.
combineReducers에 전달되는 모든 리듀서는 다음 규칙을 준수해야 합니다:
-
인식할 수 없는 액션에 대해서는 첫 번째 인자로 받은
state를 그대로 반환해야 합니다. -
절대
undefined를 반환해서는 안 됩니다. 실수로return문을 조기에 작성해 이를 저지르기 쉽기 때문에,combineReducers는 오류가 다른 곳에서 나타나게 두는 대신 즉시 예외를 발생시킵니다. -
전달받은
state가undefined인 경우, 해당 리듀서의 초기 상태를 반환해야 합니다. 앞선 규칙에 따라 초기 상태 역시undefined가 아니어야 합니다. 선택적 인자 문법으로 지정하는 것이 편리하지만, 첫 번째 인자가undefined인지 명시적으로 확인할 수도 있습니다.
combineReducers는 리듀서가 이러한 규칙을 준수하는지 확인하려 시도하지만, 여러분이 직접 규칙을 기억하고 최대한 따르는 것이 중요합니다. combineReducers는 리듀서에 undefined를 전달해 검증을 수행합니다. 이는 Redux.createStore(combineReducers(...), initialState)로 초기 상태를 지정한 경우에도 동일하게 실행됩니다. 따라서 실제 코드에서 undefined를 받을 계획이 없더라도, 리듀서가 undefined 상태를 수신할 때 올바르게 작동하도록 반드시 보장해야 합니다.
예제
reducers/todos.js
export default function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return state.concat([action.text])
default:
return state
}
}
reducers/counter.js
export default function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
reducers/index.js
import { combineReducers } from '@reduxjs/toolkit'
import todos from './todos'
import counter from './counter'
export default combineReducers({
todos,
counter
})
App.js
import { configureStore } from '@reduxjs/toolkit'
import reducer from './reducers/index'
const store = configureStore({
reducer
})
console.log(store.getState())
// {
// counter: 0,
// todos: []
// }
store.dispatch({
type: 'ADD_TODO',
text: 'Use Redux'
})
console.log(store.getState())
// {
// counter: 0,
// todos: [ 'Use Redux' ]
// }
활용 팁
-
이 헬퍼는 단순히 편의를 위한 도구입니다! 다르게 동작하는
combineReducers를 직접 작성하거나, 자식 리듀서들로부터 상태 객체를 수동으로 조합하여 다른 함수를 작성하듯이 루트 리듀서 함수를 명시적으로 작성할 수도 있습니다. -
combineReducers는 리듀서 계층 구조의 어떤 수준에서든 호출할 수 있습니다. 반드시 최상위에서만 사용해야 하는 것은 아닙니다. 실제로 너무 복잡해진 자식 리듀서를 독립적인 하위 리듀서들로 분할하기 위해 다시 사용할 수 있으며, 이 과정을 계속해서 반복할 수 있습니다.