Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add third argument state to combineReducer. add some documentation #2795

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/api/combineReducers.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ rootReducer = combineReducers({potato: potatoReducer, tomato: tomatoReducer})
// This would produce the following state object
{
potato: {
// ... potatoes, and other state managed by the potatoReducer ...
// ... potatoes, and other state managed by the potatoReducer ...
},
tomato: {
// ... tomatoes, and other state managed by the tomatoReducer, maybe some nice sauce? ...
Expand All @@ -32,6 +32,7 @@ A popular convention is to name reducers after the state slices they manage, so
#### Arguments

1. `reducers` (*Object*): An object whose values correspond to different reducing functions that need to be combined into one. See the notes below for some rules every passed reducer must follow.
1. `state` (*Object*) (Optional): Will make the entire state available in the reducer.

> Earlier documentation suggested the use of the ES6 `import * as reducers` syntax to obtain the reducers object. This was the source of a lot of confusion, which is why we now recommend exporting a single reducer obtained using `combineReducers()` from `reducers/index.js` instead. An example is included below.

Expand Down
22 changes: 19 additions & 3 deletions docs/recipes/reducers/BeyondCombineReducers.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function someSpecialActionCreator() {
return (dispatch, getState) => {
const state = getState();
const dataFromB = selectImportantDataFromB(state);

dispatch({
type : "SOME_SPECIAL_ACTION",
payload : {
Expand All @@ -69,7 +69,7 @@ A third approach would be to use the reducer generated by `combineReducers` to h
const combinedReducer = combineReducers({
a : sliceReducerA,
b : sliceReducerB
});
});

function crossSliceReducer(state, action) {
switch(action.type) {
Expand All @@ -91,6 +91,23 @@ function rootReducer(state, action) {
}
```

A fourth approach would be to pass the slice-reducers state as a third argument. This method is suitable for testability.

```js


function sliceReducer(state, action, entireState) {
switch(action.type) {
case "SOME_SPECIAL_ACTION" : {
const stateA = entireState.a
return {...state, doSomething(stateA)}
}
default : return state;
}
}

```

As it turns out, there's a useful utility called [reduce-reducers](https://github.com/acdlite/reduce-reducers) that can make that process easier. It simply takes multiple reducers and runs `reduce()` on them, passing the intermediate state values to the next reducer in line:

```js
Expand All @@ -116,4 +133,3 @@ const rootReducer = combineReducers({
Note that `combineReducers` doesn't know or care that there's anything special about the reducer function that's responsible for managing `a`. We didn't need to modify `combineReducers` to specifically know how to undo things - we just built up the pieces we needed into a new composed function.

Also, while `combineReducers` is the one reducer utility function that's built into Redux, there's a wide variety of third-party reducer utilities that have published for reuse. The [Redux Addons Catalog](https://github.com/markerikson/redux-ecosystem-links) lists many of the third-party utilities that are available. Or, if none of the published utilities solve your use case, you can always write a function yourself that does just exactly what you need.

2 changes: 1 addition & 1 deletion src/combineReducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export default function combineReducers(reducers) {
const key = finalReducerKeys[i]
const reducer = finalReducers[key]
const previousStateForKey = state[key]
const nextStateForKey = reducer(previousStateForKey, action)
const nextStateForKey = reducer(previousStateForKey, action, state)
if (typeof nextStateForKey === 'undefined') {
const errorMessage = getUndefinedStateErrorMessage(key, action)
throw new Error(errorMessage)
Expand Down