npm package: @minadmin/redux-immutable-ts
Description: redux-immutable-ts is used to create an equivalent function of Redux combineReducers that works with Immutable.js state which is written in typescript.
Author: Gajus Kuizinas
Latest version: 0.2.1

# `redux-immutable-ts`

[![GitSpo Mentions](https://gitspo.com/badges/mentions/gajus/redux-immutable?style=flat-square)](https://gitspo.com/mentions/gajus/redux-immutable)
[![Travis build status](http://img.shields.io/travis/gajus/redux-immutable/master.svg?style=flat-square)](https://travis-ci.org/gajus/redux-immutable)
[![NPM version](http://img.shields.io/npm/v/redux-immutable.svg?style=flat-square)](https://www.npmjs.org/package/redux-immutable)
[![Canonical Code Style](https://img.shields.io/badge/code%20style-canonical-blue.svg?style=flat-square)](https://github.com/gajus/canonical)

`redux-immutable` is used to create an equivalent function of Redux [`combineReducers`](http://redux.js.org/docs/api/combineReducers.html) that works with [Immutable.js](https://facebook.github.io/immutable-js/) state.

When Redux [`createStore`](https://github.com/reactjs/redux/blob/master/docs/api/createStore.md) `reducer` is created using `redux-immutable` then `initialState` must be an instance of [`Immutable.Collection`](https://facebook.github.io/immutable-js/docs/#/Collection).

## Problem

When [`createStore`](https://github.com/reactjs/redux/blob/v3.0.6/docs/api/createStore.md) is invoked with `initialState` that is an instance of `Immutable.Collection` further invocation of reducer will [produce an error](https://github.com/reactjs/redux/blob/v3.0.6/src/combineReducers.js#L31-L38):

> The initialState argument passed to createStore has unexpected type of "Object".
> Expected argument to be an object with the following keys: "data"

This is because Redux `combineReducers` [treats `state` object as a plain JavaScript object](https://github.com/reactjs/redux/blob/v3.0.6/src/combineReducers.js#L120-L129).

`combineReducers` created using `redux-immutable` uses Immutable.js API to iterate the state.

## Usage

Create a store with `initialState` set to an instance of [`Immutable.Collection`](https://facebook.github.io/immutable-js/docs/#/Collection):

```js
import { combineReducers } from "redux-immutable";

import { createStore } from "redux";

const initialState = Immutable.Map();
const rootReducer = combineReducers({});
const store = createStore(rootReducer, initialState);
```

By default, if `state` is `undefined`, `rootReducer(state, action)` is called with `state = Immutable.Map()`. A different default function can be provided as the second parameter to `combineReducers(reducers, getDefaultState)`, for example:

```js
const StateRecord = Immutable.Record({
  foo: "bar"
});
const rootReducer = combineReducers({ foo: fooReducer }, StateRecord);
// rootReducer now has signature of rootReducer(state = StateRecord(), action)
// state now must always have 'foo' property with 'bar' as its default value
```

When using `Immutable.Record` it is possible to delegate default values to child reducers:

```js
const StateRecord = Immutable.Record({
  foo: undefined
});
const rootReducer = combineReducers({ foo: fooReducer }, StateRecord);
// state now must always have 'foo' property with its default value returned from fooReducer(undefined, action)
```

In general, `getDefaultState` function must return an instance of `Immutable.Record` or `Immutable.Collection` that implements `get`, `set` and `withMutations` methods. Such collections are `List`, `Map` and `OrderedMap`.

### Using with `react-router-redux` v4 and under

`react-router-redux` [`routeReducer`](https://github.com/reactjs/react-router-redux/tree/v4.0.2#routerreducer) does not work with Immutable.js. You need to use a custom reducer:

```js
import Immutable from "immutable";
import { LOCATION_CHANGE } from "react-router-redux";

const initialState = Immutable.fromJS({
  locationBeforeTransitions: null
});

export default (state = initialState, action) => {
  if (action.type === LOCATION_CHANGE) {
    return state.set("locationBeforeTransitions", action.payload);
  }

  return state;
};
```

Pass a selector to access the payload state and convert it to a JavaScript object via the [`selectLocationState` option on `syncHistoryWithStore`](https://github.com/reactjs/react-router-redux/tree/v4.0.2#history--synchistorywithstorehistory-store-options):

```js
import { browserHistory } from "react-router";
import { syncHistoryWithStore } from "react-router-redux";

const history = syncHistoryWithStore(browserHistory, store, {
  selectLocationState(state) {
    return state.get("routing").toJS();
  }
});
```

The `'routing'` path depends on the `rootReducer` definition. This example assumes that `routeReducer` is made available under `routing` property of the `rootReducer`.

### Using with `react-router-redux` v5

To make [`react-router-redux` v5](https://github.com/ReactTraining/react-router/tree/master/packages/react-router-redux) work with Immutable.js you only need to use a custom reducer:

```js
import { Map } from "immutable";
import { LOCATION_CHANGE } from "react-router-redux";

const initialState = Map({
  location: null,
  action: null
});

export function routerReducer(
  state = initialState,
  { type, payload = {} } = {}
) {
  if (type === LOCATION_CHANGE) {
    const location = payload.location || payload;
    const action = payload.action;

    return state.set("location", location).set("action", action);
  }

  return state;
}
```