Skip to content

Commit

Permalink
Add composeReducers (#33)
Browse files Browse the repository at this point in the history
Add composeReducers
  • Loading branch information
esamattis authored Jul 10, 2019
2 parents af27477 + ebd2c3e commit fb52bf7
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 24 deletions.
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,3 +352,34 @@ Example
```ts
setPrefix("MY_APP");
```

### `function composeReducers<State>(...reducers)`

Utility that reduces actions by applying them through multiple reducers.
This helps in allowing you to split up your reducer logic to multiple `ImmerReducer`s
if they affect the same part of your state

Example

```ts
class MyNameReducer extends ImmerReducer<NamesState> {
setFirstName(firstName: string) {
this.draftState.firstName = firstName;
}

setLastName(lastName: string) {
this.draftState.lastName = lastName;
}
}

class MyAgeReducer extends ImmerReducer<AgeState> {
setAge(age: number) {
this.draftState.age = 8;
}
}

export const reducer = composeReducers(
createReducerFunction(MyNameReducer, initialState),
createReducerFunction(MyAgeReducer, initialState)
)
```
25 changes: 1 addition & 24 deletions __tests__/immer-reducer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
ImmerReducer,
createReducerFunction,
createActionCreators,
composeReducers,
setPrefix,
_clearKnownClasses,
isAction,
Expand All @@ -10,35 +11,11 @@ import {

import {createStore, combineReducers, Action} from "redux";

interface Reducer<State> {
(state: State | undefined, action: any): State;
}

beforeEach(_clearKnownClasses);

afterEach(() => {
setPrefix("IMMER_REDUCER");
});
/**
* Combine multiple reducers into a single one
*
* @param reducers two or more reducer
*/
function composeReducers<State>(
...reducers: (Reducer<State | undefined>)[]
): Reducer<State> {
return (state: any, action: any) => {
return (
reducers.reduce((state, subReducer) => {
if (typeof subReducer === "function") {
return subReducer(state, action);
}

return state;
}, state) || state
);
};
}

test("can create reducers", () => {
const initialState = {foo: "bar"};
Expand Down
25 changes: 25 additions & 0 deletions src/immer-reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,31 @@ export function isActionFrom<T extends ImmerReducerClass>(
return isActionFromClass(action, immerReducerClass);
}

interface Reducer<State> {
(state: State | undefined, action: any): State;
}

/**
* Combine multiple reducers into a single one
*
* @param reducers two or more reducer
*/
export function composeReducers<State>(
...reducers: (Reducer<State | undefined>)[]
): Reducer<State> {
return (state: any, action: any) => {
return (
reducers.reduce((state, subReducer) => {
if (typeof subReducer === "function") {
return subReducer(state, action);
}

return state;
}, state) || state
);
};
}

/** The actual ImmerReducer class */
export class ImmerReducer<T> {
static customName?: string;
Expand Down

0 comments on commit fb52bf7

Please sign in to comment.