npm package: @kubric/reduxutils
Description: Utility functions for redux reducers and state management
Author: Jophin Joseph
Latest version: 1.0.0

# reduxutils

Utility functions for redux reducers and state management

## Installation

```JavaScript
npm install @kubric/reduxutils
```

or

```JavaScript
yarn add @kubric/reduxutils
```

## Functions

### composeReducers(reducers, defaultState)

Accepts an array of reducers and a default state and returns a single reducer. Any incoming action to the final reducer passes through all the reducers(from left to right). The state passed to a reducer will be the state generated by the reducer on its left

#### Example

```JavaScript
import { composeReducers } from "@kubric/reduxutils";

const actions = {
  ADD: 'ADD'
};

const reducer1 = (state = {}, action, extraData) => {
  switch (action.type) {
    case actions.ADD:
      return {
        ...state,
        one: 1
      };
    default:
      return state;
  }
};

const reducer2 = (state = {}, action, extraData) => {
  switch (action.type) {
    case actions.ADD:
      return {
        ...state,
        two: 2
      };
    default:
      return state;
  }
};

let composedReducer = composeReducers([
    reducer1,
    reducer2,
], {
    four: 4
});

let results = composedReducer({
    four: 4
}, {
    type: actions.ADD,
}, { three: 3 });
//results will be
// {
//   four: 4,
//   one: 1,
//   two: 2
// }
```

### combineReducers(reducerMap, options)

The same implementation of the redux [`combineReducers`](https://redux.js.org/api/combinereducers) with 2 changes

1. If more arguments are passed to the combined reducer after `state` and `action`, these parameters will be passed on to all the individual reducers
2. `options.ignoreNonReducerKeys`: The redux `combineReducers` will ignore keys in the input state that do not have a corresponding reducer in the `reducerMap`. The behavior can be controlled with this option. If `true`, it will behave exactly like the redux `combineReducers`. If `false`(default), it will evaluate keys that have reducers and copy over keys(from the input state) that do not have a reducer associated with it

#### Example

```JavaScript
import combineReducers from "../src/combinereducers";

const actions = {
  ADD: 'ADD'
};

const reducer1 = (state = {}, action, extraData = { one: "one" }) => {
  switch (action.type) {
    case actions.ADD:
      return {
        ...state,
        one: extraData.one
      };
    default:
      return state;
  }
};

const reducer2 = (state = {}, action, extraData = { two: "two" }, moreData = "three") => {
  switch (action.type) {
    case actions.ADD:
      return {
        ...state,
        two: extraData.two,
        three: moreData
      };
    default:
      return state;
  }
};

let combinedReducer = combineReducers({
  reducer1,
  reducer2,
});

let results = combinedReducer({
    four: 4
}, {
    type: actions.ADD,
}, {
  one: 1,
  two: 2
}, 3);
//results will be
// {
//     one: 1,
//     two: 2,
//     three: 3,
//     four: 4
// }
```

### batchedActionReducer(reducer, options)

Generates a new reducer that can handle a batch of actions in a single state update. A batch of actions is just another action, that has

1. A `type` that is provided while generating the batch processing reducer
2. An array of action objects that can be found at a `path` that is specified at the time of generating the reducer

#### options

* `type`: Type of the action that will be dispatched to the state if it is a batched action. Default - `BATCHED_ACTION`
* `path`: The path within the batched action object where the batched reducer looks for the array of actions that need to be evaluated by the reducer. Default - `payload`

#### Example

```JavaScript
import { batchedActionReducer } from "@kubric/reduxutils";

const actions = {
  ONE: 'ONE',
  TWO: 'TWO',
  THREE: 'THREE'
};

const reducer = (state = {}, action = {}) => {
  switch (action.type) {
    case actions.ONE:
      return {
        ...state,
        one: 1
      };
    case actions.TWO:
      return {
        ...state,
        two: 2
      };
    case actions.THREE:
      return {
        ...state,
        three: 3
      };
    default:
      return state;
  }
};

const batchedReducer = batchedActionReducer(reducer);

const results = batchedReducer({ four: 4 }, {
    type: "BATCHED_ACTION",
    payload: [{
      type: actions.ONE
    }, {
      type: actions.TWO
    }]
});
// results
// {
//     four: 4,
//     one: 1,
//     two: 2
// }
```

### patchState(state, patch, options)

Patches the redux state(string/array/object) with a value doing a shallow clone along the path where the patch is being applied

#### options

* `path`: path in the state at which the patch has to be applied. If the path is non existent, then it will be created and then the patch will be applied.
* `at`: If the current value in the path is an array or string, then the at parameter defines at which position in the array/string the patch needs to be applied

#### Example

An exhaustive list of examples can be found in the [test cases](tests/patchstate.test.js) for this function.