5

Right now I'm using reselect to create my selectors to extract data from the store and pass it to the props via connect. For simplicity, the result of my selectors is always a JS object (calling toJS() at the end of the selector), something like this:

const selector = state => state.get('data').toJS();

Now I'm trying to improve some performance and I realized that shouldComponentUpdate shallow comparison loses the advantages of immutability because of the way I'm returning from my selectors.

On the other hand, using .get('prop') inside my html seems extremely annoying:

<div>{this.props.data.get('prop')}</div>

Especially if I have a case of passing a simple JS object to a child component which is mutable, like this:

<ChildComponent totalItems={10} />

And then there is no consistency when accessing the props (some are mutable and some are immutable).

I thought of creating an helper unwrap function, something like this:

const unwrap = obj => obj && obj.toJS ? obj.toJS() : obj;

But I don't really like this solution.. I don't really like any of those approaches.

What do you use for both clean code & performance?

Adam Tal
  • 5,911
  • 4
  • 29
  • 49

3 Answers3

2

To pass props to component collect all data under a key as immutable.

<MyComponent propsKey={Immutable.fromJS({someData: {key: "value"}})} />

To use benefits of Immutable you should avoid from use toJS(). It is very costly and you cannot use useful Immutable functions with that. Until you reach "value", you should use Immutable.get(). It is annoying at first but, you can see how it is useful and easy to use, in time. (To get inner keys using getIn() can be less annoying than chain get functions). In this way your code can work more efficient and you do not need to use unwrap function, in your component you guarantee your data under this.props.propsKey always immutable.

Dilek Gencer
  • 131
  • 2
  • I agree with the second part of your answer. But the example of using `Immutable.fromJS` inside my markup is even more disturbing than having a mixed mutable/immutable props.. – Adam Tal Aug 23 '16 at 06:17
  • Your props data are always will be immutable but if you have new data in your component and need to pass it into child component, Immutable.fromJS() is a good approach to pass all props as immutable again – Dilek Gencer Aug 23 '16 at 16:03
  • To me, the real value in using Immutable only shines through if you use Immutable all the way down the stack. This is what allows you to use a naÏve implementation of shouldComponentUpdate in all your components. I think calling toJS is a HORRIBLE idea. Would you call JSON.stringify/JSON.parse in your selector? – rooftop Aug 26 '16 at 13:37
1

You should wrap your presentational components in a simple higher-order component that calls toJS() on any Immutable.js object props passed to it.

This will give you the best balance of keeping the performance benefits of Immutable.js whilst keeping your container components from re-rendering too much, as well as keeping your presentational components dependency-free and therefore easily reusable and testable.

The Redux docs have a good selection of best practises for using Immutable.js, in particular, when not to use .toJS(), why your presentational components should be kept pure and how a "toJS" higher-order component might be defined and used.

Community
  • 1
  • 1
Matt Read
  • 33
  • 6
0

Coming back to my question a year and a half later with my own answer:

Always pass the immutable object if possible. If it's not immutable, just pass it as it is.

I decided that performance is much more important than how pretty the code is.

If a value is either immutable or mutable I pass it as it is and never call toJS if I don't have to. I also won't wrap mutable values with fromJS if they're not stored in the redux store.

I just need to be aware inside the child component that some props are immutable and some are not - and it's actually pretty simple because almost always a complex object will be immutable.

Adam Tal
  • 5,911
  • 4
  • 29
  • 49