How to use Immutable.js with shorthand?

Redux uses reducers to change the state of an application in response to an action.

The key requirement is that the reducer cannot modify an existing state object; he must create a new object.

Bad example :

import { ACTIVATE_LOCATION } from './actions'; export let ui = (state = [], action) => { switch (action.type) { case ACTIVATE_LOCATION: state.activeLocationId = action.id; break; } return state; }; 

Good example :

 import { ACTIVATE_LOCATION } from './actions'; export let ui = (state = [], action) => { switch (action.type) { case ACTIVATE_LOCATION: state = Object.assign({}, state, { activeLocationId: action.id }); break; } return state; }; 

This is a good use case for Immutable.js .

+47
javascript redux
Aug 08 '15 at 11:44
source share
5 answers

Taking your good example with the same

 import { ACTIVATE_LOCATION } from './actions'; import { Map } from 'immutable'; const initialState = Map({}) export let ui = (state = initialState, action) => { switch (action.type) { case ACTIVATE_LOCATION: return state.set('activeLocationId', action.id); default: return state; } }; 
+45
Aug 09 '15 at 0:25
source share

Immutable.js should be used in each reducer as necessary, for example

 import { ACTIVATE_LOCATION } from './actions'; import Immutable from 'immutable'; export let ui = (state, action) => { switch (action.type) { case ACTIVATE_LOCATION: state = Immutable .fromJS(state) .set('activeLocationId', action.id) .toJS(); break; } return state; }; 

However, this example has a lot of overhead: every time a reducer action is called, it must convert the JavaScript object to an Immutable instance, mutate the resulting object, and convert it back to a JavaScript object.

A better approach is to have an initial state of an Immutable instance:

 import { ACTIVATE_LOCATION } from './actions'; import Immutable from 'immutable'; let initialState = Immutable.Map([]); export let ui = (state = initialState, action) => { switch (action.type) { case ACTIVATE_LOCATION: state = state.set('activeLocationId', action.id); break; } return state; }; 

Thus, you only need to convert the initial state to an instance of Immutable ounce. Then each reducer will consider it as an Immutable instance and pass it line by line as an Immutable instance. The trick is that now you need to pass all the JavaScript state before passing the values ​​to the view context.

If you perform multiple state mutations in a reducer, you may need batch mutations using .withMutations .

To simplify the task, I developed the redux-immutable library. It provides a function combineReducers , equivalent to a function of the same name in the redux package, except that it expects the initial state and all reducers to work unchanged. js .

+23
Aug 08 '15 at 11:44
source share

If you are just looking for an easy way to make updates without mutation, I support the library: https://github.com/substantial/updeep , which in my opinion is a good way to do this with redux .

updeep allows updeep to work with regular (frozen) hierarchies of objects, so you can perform destructuring, view objects in logs and the debugger, etc. It also has a powerful API that allows batch updates. It will not be as efficient as Immutable.js for large datasets, because it clones objects if necessary.

Here is an example (but check them again in README):

 import { ACTIVATE_LOCATION } from './actions'; import u from 'updeep'; export let ui = (state = [], action) => { switch (action.type) { case ACTIVATE_LOCATION: state = u({ activeLocation: action.id }, state); break; } return state; }; 
+8
Aug 08 '15 at 17:25
source share

The accepted answer should not be the accepted answer. You need to initialize the state using immutable and, as mentioned above, using redux-immutablejs

 const initialState = Immutable.fromJS({}) // or Immutable.Map({}) const store = _createStore(reducers, initialState, compose( applyMiddleware(...middleware), window.devToolsExtension ? window.devToolsExtension() : f => f )); 

How to use combReducers from redux-immutablejs

Extra tip: Using response-router-redux works very well, so if you want to add this, replace the reducer with response-router-redux as follows:

 import Immutable from 'immutable'; import { UPDATE_LOCATION } from 'react-router-redux'; let initialState; initialState = Immutable.fromJS({ location: undefined }); export default (state = initialState, action) => { if (action.type === UPDATE_LOCATION) { return state.merge({ location: action.payload }); } return state; }; 

Just import it into your root reducer

This is also indicated in the documentation for shorthand-immutablejs

+5
Feb 11 '16 at 1:39
source share

Take a look at https://github.com/indexiatech/redux-immutablejs

This is pretty much combineReducer and an optional createReducer that meets Redux standards.

+2
Sep 04 '15 at 15:38
source share



All Articles