Immutable.js .get() vs. .getIn()

At Sprout Social in some areas of our frontend app we use Immutable.js for our Redux store.

Standardizing Selector Styles.

When selecting state out of our store we’ve written a collection of selectors to consolidate selectors logic. We’ve always write these selectors in array notation to keep styles consistent.

In theory we could share our array paths between our selectors and our reducers as constant. In addition lodash also supports array styled paths for _.get() which can be convenient for sharing paths.

With all selectors written in array notation, for Immutable.js we use .getIn() by default — regardless if the path is only one key deep.

Immutable.js .get() vs. .getIn()

However it is always faster to do a .get() than a .getIn() , namely because for a .getIn() Immutable will have to iterate through an array and check the resulting path along the way. This therefore makes .get() ultimately cheaper.

Abstract .getIn()

So if we wish to keep all selectors a consistent style, but take advantage of .get() whenever possible, the first thing to do is to create an abstraction for Immutable .getIn() — something like this:

Add .get() to the abstraction.

How could we get this handy abstraction to take advantage of .get() whenever possible?
We could peak into the arrayPath , if there is only one value, use plain old get. In addition we may want to make sure no developer is expecting to use . notation paths.

But is it performant?

Array length checking and string checking is cheap. With a quick little JSPerf test we can see immediately with these checks, using .get() is still more than twice as fast as .getIn().

In the end

In the end, this is a micro optimization. However, we saw ~30ms to ~150ms speedups for for various actions in the app. It really depends on the how often your selectors run. We have a large number of selectors that fire quite a bit. With such a small change, we’ll gladly take any performance boost over 100ms.

Don’t worry about the abstraction, just remember to prefer.get() over .getIn() whenever possible.

Pro tip: Same goes for .set() / .setIn() and .update() / .updateIn(), etc.