Redux: How to initialize redux with immutable object

Created on 20 Jun 2015  ·  26Comments  ·  Source: reduxjs/redux

Is it possible or I'm doing smt wrong?

let initialState = immutable.fromJS({some_store: "some initial data"});
const redux = createRedux(stores, initialState);
...
export function some_store(state, action) {
    // state is undefined here
}
help wanted question

Most helpful comment

@jsifalda

Pros of using Immutable with Redux:

  • You can't mutate by mistake
  • Way faster performance and better memory consumption with large arrays and objects

Cons of using Immutable with Redux:

  • New API to learn for your team
  • Increased bundle size
  • Slightly trickier to debug

The tradeoff is up to you!

All 26 comments

I think what you want is something like this

// stores/some-store.js
import Immutable from 'immutable'

const { Map, List, fromJS } = Immutable
const initialState = Map({
  foo: 'bar',
  fooList: List()
})

export function someStore (state = initialState, action) {
  if (action.type === 'FOO') {
    return state.set('foo', fromJS(action.foo))
  }
  if (action.type === 'FOO_LIST') {
    return state.set('fooList', fromJS(action.fooList))
  }

  return state
}

// stores/index.js
export { default as someStore } from './some-store'

// application.js
import * as stores from './stores'

const redux = createRedux(stores)

You should let stores define their own initial state using default parameter like @emmenko showed.

The initialState argument is only meant to be used for rehydrating state from server or localStorage. (@acdlite, we might want to explain this in docs.)

That said, what you tried should work. Can somebody investigate?

No, what I tried does not work. I just want to create initial data for all stores in one place. I guess this is what I shouldn't do.

I just want to create initial data for all stores in one place. I guess this is what I shouldn't do.

It's up to you. I find it better to divide the initial data.

Still, if something doesn't work, let's keep it open? I'll revisit next week and see why it did not work.

The problem is with composeStores that is assuming the root state is a plain JS object, and accessing the properties with state[key], which fails with Immutable.Map. I think it may work with Immutable.Record since that makes the fields accessible via regular JS properties.

There may be other places where it's assuming a plain object though.

Oh. That's a great catch! Thanks for explaining. This makes perfect sense.

Using connectors also fails for the very same reason: isPlainObject(Immutable.Record) === false .

@pierregm This is actually correct. If it spread the Record properties over the component props, that wouldn't work anyway. It is up to you to write select={state => state.get('something').toJS()}.

I was able to get it to work like this,

// store
const initialState = Immutable.fromJS({}).toOrderedMap();

export default function streamStore(state = initialState, action) {
  switch (action.type) {

    case actionTypes.FETCH_STREAM_DONE:
      var streamMap = {};

      for (var i in action.stream_data) {
        var item = action.stream_data[i];
        streamMap[item.id] = item;
      }
      return state.merge(Immutable.fromJS(streamMap).toOrderedMap());

    default:
      return state
  }
};

// select
function select(state) {
  return {stream: state.stream.toList()}
}

It works perfectly but it ends up re-rendering all items in the stream (a list view). I was wondering how one could implement something that compares the old state vs new state at store level and invalidates the need to render any components right there when there are no changes to the data. NuclearJS does this with Immutable structures. What would the recommended way be to implement something like that in redux?

@owais

Check out Reselect: https://github.com/faassen/reselect. It provides functionality similar to NuclearJS getters.

@gaearon Cool! Great talk at ReactEurope BTW! Thanks.

This is my attempt to use Immutable.js with redux 1.0.0, https://github.com/gajus/redux-immutable

Nice @gajus! Testing out redux-immutable now and really liking the https://github.com/gajus/canonical-reducer-composition pattern

Thank you @chiplay. I would really appreciate feedback should you come across deficiencies or have ideas for improvement.

is there any advantage of using immutable structures together with redux? when the redux is based on immutable behaviour (eg. stores return new copy of state)? Performance (any benchmarks?)? or something else? thx

@jsifalda

Pros of using Immutable with Redux:

  • You can't mutate by mistake
  • Way faster performance and better memory consumption with large arrays and objects

Cons of using Immutable with Redux:

  • New API to learn for your team
  • Increased bundle size
  • Slightly trickier to debug

The tradeoff is up to you!

@gaearon
thank you very much for fast and helpful answer!

If you want ImmutableJs & Redux that conforms Redux standards you can take a look at https://github.com/indexiatech/redux-immutablejs,

@gaearon Is it possible to put a link on the web site ?

Thank you Asaf. I am sure people will find it useful.

On Sep 4, 2015, at 18:36, Asaf Shakarchi [email protected] wrote:

If you want ImmutableJs & Redux that conforms Redux standards you can take a look at https://github.com/indexiatech/redux-immutablejs,

@gaearon Is it possible to put a link on the web site ?


Reply to this email directly or view it on GitHub.

@asaf

Good stuff, would you like to make a PR to Ecosystem.md?
I will happily add it there if you add tests to your project.

@gaearon Done with unit tests, PR is: https://github.com/rackt/redux/pull/707

Thanks!

Hi all,
a little question for @gaearon, from the quick tests I've done so far to implement ImmutableJS on my existing React / Redux app, it feels a little slower :-/ but perhaps am I doing something in a wrong way...

Basic use case : getting a collection of data from an API call and storing it in a reducer...

From my reducer,
Without ImmutableJS :

const initialStore = {
    isLoading : false,
    error     : null,
    data      : []
}

// in the switch case
return {
   ...state,
   isLoading: false,
   error: null,
   data: action.result
}

With ImmutableJS

const initialStore = Map({
    isLoading : false,
    error     : null,
    data      : List()
})

// in the handler function
return state.merge({
    isLoading: false,
    error: null,
    data: List(result.result)
})

I am wondering if the "treatment" ImmutableJS is doing isn't costing more here ?

From what I understand from Immutability, the benefit is more when the rendering quicks in, right ?

Thanks for your feedback.

The benefit is that operating on large arrays and objects costs less memory and works faster. It doesn't make a large difference in small applications.

Ok, thanks.
So I've got the right approach anyway ?

Yeah, looks good to me.

So far the trade off has been worth it.. 💯

Was this page helpful?
0 / 5 - 0 ratings