Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to initialize redux with immutable object #153

Closed
amorphius opened this issue Jun 20, 2015 · 26 comments
Closed

How to initialize redux with immutable object #153

amorphius opened this issue Jun 20, 2015 · 26 comments

Comments

@amorphius
Copy link

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
}
@emmenko
Copy link
Contributor

emmenko commented Jun 20, 2015

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)

@gaearon
Copy link
Contributor

gaearon commented Jun 20, 2015

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?

@amorphius
Copy link
Author

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.

@gaearon
Copy link
Contributor

gaearon commented Jun 20, 2015

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.

@gaearon gaearon reopened this Jun 20, 2015
@leoasis
Copy link
Contributor

leoasis commented Jun 20, 2015

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.

@gaearon
Copy link
Contributor

gaearon commented Jun 20, 2015

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

@pierregm
Copy link

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

@gaearon
Copy link
Contributor

gaearon commented Jun 29, 2015

@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()}.

@owais
Copy link

owais commented Jul 5, 2015

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?

@gaearon
Copy link
Contributor

gaearon commented Jul 5, 2015

@owais

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

@owais
Copy link

owais commented Jul 5, 2015

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

@gajus
Copy link
Contributor

gajus commented Aug 8, 2015

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

@chiplay
Copy link

chiplay commented Aug 17, 2015

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

@gajus
Copy link
Contributor

gajus commented Aug 17, 2015

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

@jsifalda
Copy link

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

@gaearon
Copy link
Contributor

gaearon commented Aug 26, 2015

@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!

@jsifalda
Copy link

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

@asaf
Copy link
Contributor

asaf commented Sep 4, 2015

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 ?

@gajus
Copy link
Contributor

gajus commented Sep 4, 2015

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

On Sep 4, 2015, at 18:36, Asaf Shakarchi notifications@github.com 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.

@gaearon
Copy link
Contributor

gaearon commented Sep 4, 2015

@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.

@asaf
Copy link
Contributor

asaf commented Sep 10, 2015

@gaearon Done with unit tests, PR is: #707

Thanks!

@websilone
Copy link

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.

@gaearon
Copy link
Contributor

gaearon commented Nov 6, 2015

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.

This was referenced Jan 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests