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

https://jsperf.com/immutable-get-getin-path-check/1

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.

Why I left Windows behind.

Ever since my youth I was Windows fanboy and a Mac hater. I swore to never ever become like those “Mac fanboys“, I scoffed even at the idea…

Alas – My newly found pains with Windows:

1. Background services are priority over focused application

I have a theory that Windows prioritizes Services over the focused application. It is very rare that I see an app on my Mac ‘hang’ or get slow. Hanging apps just sometimes happen on Windows and you sit and wait. This may be why clicking things sometimes feels slightly slow.

2. Slow to open an Application

If I were to race my Mac and Windows opening identical applications, my money would be on my Mac. Can’t say why, but clicking things just happen faster on the mac.

2. Latency between click and response

On a Mac clicking something seems to happen ‘now’ as appose to in a moment on Windows. The time difference is probably only a handful of milliseconds. Perhaps Windows just likes to animate transitions bit more, but snappiness certainly feels better.

3. Heavy OS

Windows seems to like to make itself visible via animations, sounds, alerts, task bar notifications. Sometimes I just want to focus, but Windows has something it thinks is important for me now. I can’t help but feel that Windows has many moving parts that aren’t per-se coordinated.

5. Stability over time

With age, a Windows machine get’s bogged down by … something. Clutter of background services, taskbar apps, updaters, or something. But even cleaning these up and defragging only seems to go so far. Wiping the and reloading seems to be the only surefire way to make a Windows machine truly fast again. On my Mac, I swear I just have to reboot it (because it’s probably been  month).

6. Frequent reboots required

Speaking of reboots. I’ve had my Mac hit 100+ days of uptime with hardly any issues. This is completely unheard of in the Windows universe. Having an uptime of 7 days, is pretty good for a Windows machine (I have managed 60 +days, but it’s pretty rough by then). With a Windows machine the default it to ‘shut it down’. They just weren’t built for longevity. You constantly must reboot.

7. Long boot time and resume time

When you do reboot, it time for a coffee break. Reboot a Mac, and you might have time to stand up, stretch your arms. When in the workplace, the reboot sound on a Mac is a mark of ‘shame’. Everyone looks around for who was the one that had to reboot their Mac, *gasp*.

8. Sounds, sounds everywhere

Speaking of sounds. Why must every-little-thing make sounds on a Windows machine. Am I right angry little elephant Windows sound? Turning off Windows sounds is the first thing I do on a new install of Windows. Every once and a while they turn themselves back on when you accidentally set a theme instead of a new wallpaper.

9. Lack of SSH

Not to say you can’t install SSH, but the lack of it is a bit of a bummer I can’t SSH from just any Windows machine. Though I hear this has recently changed maybe.


Well thems my thoughts. With all that said… Ironically I still love and use my Windows machines. I didn’t really leave it behind.

React “statePropsPrecalculationError” and TypeError ‘state’ of undefined

Debugging a React component can be a pain.

There are many causes for “statePropsPrecalculationError”, for debugging see my post on Debugging React statePropsPrecalculationError post.

When you specifically have ” ‘state’ of undefined” the fix is simple:

Recently I ran into “statePropsPrecalculationError” alongside with the the console warning TypeError: Cannot read property ‘state’ of undefined(…)`.

This is super easy to fix, but not immediately obvious. Whenever you use `this.setState()` inside your component, you must define your initial state!

Just add a `getInitialState()` definition!


const MyComponent = React.createClass({
getInitialState() {
return {
isOpen: false
};
},
toggleOpen() {
this.setState({isOpen: !this.state.isOpen});
},
render() {
return (

Hello World!

);
}
});

Code: Regex for Instagram Username and Hashtags

Instagram is unique when it comes to it’s rules for usernames and hashtags. Here is one take at create a regex to detect them in JavaScript.

The rules

  • Two matches @ mentions with no space between @thebox193@discodude
  • Matches with one . in them @disco.dude but not two .. @disco..dude
  • Ending period not matched @discodude.
  • Match underscores _ @_disco__dude_
  • Max characters of 30 @1234567890123456789012345678901234567890

The RegEx

(?:@)([A-Za-z0-9_](?:(?:[A-Za-z0-9_]|(?:\.(?!\.))){0,28}(?:[A-Za-z0-9_]))?)
Instagram username RegEx

Examples

You can try it out over on Debuggex. Here is a an example implemented in JavaScript.

LoDash.js / Underscore.js mixins

Here are a few mixins I’ve created for LoDash.js I’ve found handy.

_.getDeep

/**
* Safely retrieves the value of a deeply nested object value
* @param {object} O The Object to be searched
* @param {string} str Dot notation string of the address of the attribute to be retrieved
* @return {mixed} Value of nested item or undefined
* @link http://stackoverflow.com/a/15400575/417822
*/
_.mixin({'getDeep': function(O, str) {
if ( !_.isObject(O) ) return;

var seg= str.split('.');
while(O && seg.length) {
O = O[seg.shift()];
}
return O;
}});

_.hasDeep

/**
* Tests if a deep value has a value/exists. Uses _.getDeep to retrieve value.
* @param {object} O The Object to be tested
* @param {string} str Dot notation string of the address of the attributed to be tested
* @return {boolean}
* @todo validate that falesy values 'false' '0' etc come back as true.
*/
_.mixin({'hasDeep': function(O, str) {
return !_.isUndefined( _.getDeep(O, str) );
}});

_.isDefined
Because typing !_.isUndefined() all the time is tiresome. Using _.isDefined is clear and more readable.

/**
* Shorthand for !_.isUndefined
* @param {mixed} e Item to be tested
* @return {boolean}
*/
_.mixin({'isDefined': function(e) {
return !_.isUndefined(e);
}});

_.compactObject

/**
* Removes all falsy and undefined values from an object
* @param {object} o Object to be compacted
* @return {object} Compact Object
* @link http://stackoverflow.com/a/14058408/417822
*/
_.mixin({'compactObject': function(o) {
var clone = _.clone(o);

_.each(clone, function(v, k) {
if(!v) delete clone[k];
});

return clone;
}});

_.compactObject

/**
* Toggles an array element
* @param {Array} arr Source Array
* @param {Mixed} val Value to toggle
* @param {Boolean} Optional: Boolean to determine whether to add or remove
* @return {Array} Result
*/
_.mixin({'arrayToggle': function(arr, val, state) {
if ( _.indexOf(arr,val)==-1 || state)
return _.union(arr,[val]);
else
return _.without(arr,val);
}});

Code: Data structure

In my understanding there are different types of data. Each is unique in purpose, mutability, and scope. Clearly identifying the role of an attribute and grouping it with related ones creates a cleaner interface to work with.

Raw Attributes

The raw data that is persisted to the server.

This data should be treated as if immutable, unless planning to persist a change of one of the values to the database. This is the once source of ‘truth’ that is trustworthy. If it is reformatted, or changed it looses its trustworthiness.

user: {
 firstName: 'Phil',
 lastName: 'McCool',
 username: 'pmccool'
}

Computed Values

Take in Raw Data, and reformat it for later use.

More often than not these are a convince to remove the need to repeat logic throughout the app.

If there is an urge to create a value here to describe the model’s content ‘isAdmin’, ‘fullName’, there is a good chance these ought to be part of the data schema to start with.

They can come at a cost of being computed but not always needed everywhere throughout the app. Alternately getter functions could be used to allow a more ‘on-demand’ approach (add result caching and get the both of both worlds).

computed: {
 fullName: 'Phil McCool',
 shortName: 'Phil M.',
 numberVowels: 3
}

State

Describing the state status, of either the data or of the component/view.

State data describes progress or what things are doing currently – [changing, updating, modified]. While these are similar to configuration items, they mutable are more closely tied to the model data describing what is happening to it. If their were multiple components/views that display the same model, they may all want to know the current state of the data. It’s meta data to the data.

These values should update frequently.

state: {
 isLoading: false,
 isModified: true,
 page: 4
}

Configuration

How something should be displayed or behave.

These ought be on the component/view that is rendering the item. It describes the preferences of how something should behave or be displayed. Think of them as options, ways to deviate from the norm, an API for this component/view.

A component/view should have a set of defaults for these values to fall back upon.

Config attributes can make it tempting to overload abstraction. Draw a line of making a new component/view when the core functionality has config options that cause different logic paths.

config: {
 size: 'large',
 template: 'card',
 color: 'blue'
}

 


Take Aways

It can be very tempting to merge or stuff configuration and state data right into the model data. It’s convenient, but lazy. It taints the raw data. If put an ‘isLoading’: true value into our data model then persist it to the server, we ought to feel like we did something wrong.

Ideally we would be able to group data in our actual data structures, but at minimum, we can always just keep in mind the role of an attribute and group mentally.

TL;DR

  • Not all data is alike.
  • Don’t mutate / override original data
  • Computed, State, and Config data shouldn’t be mixed in with raw data.

Code: jquery.otherdropdown.js

Today I published my first node npm package and bower package – jquery.otherdropdown! For quite a while I’ve been reusing a simple code snippet that made it possible for a user to add their own custom response to a select dropdown. I never thought I would publish it.

The principle is simple, in a list of options when the ‘other’ response is selected, prompt the user to specify what they mean. Try out the demo.

jquery.otherdropdown

I’ve seen forms that add an additional input, but it’s effective – but feels choppy to the user. Processing the data can also be slightly more complex when you have to check for a value that may or may not exist.

A long while ago I wrote a script (before jQuery was prevelent) that manipulated the DOM to give the effect I was after. Since then it’s been modified and switched to use jQuery and made it into a plugin.

The functionality is all self contained and pretty simple to use.  Use jQuery to get the select dropdown and runn the plugin on it:

$('.myDropdown').otherdropdown();

Publishing it to Bower I realized could be helpful not only to me but to everyone. Why not give it a go? Many things needed to be done, make it flexible with options for customization, create documentation and demos, and sharpen up the code. After several hours it was ready to go!

It’s been fun to work on. More complex idea are cooking.

Tips: My Favorite Sublime 3 Packages

I primarily use Sublime as my code editor of choice; a bunch of us at Sprout Social do. It’s simple, clean, lightweight on system resources, and it has some pretty sweet packages. I’ve found a number of packages that increase my efficiency developing. Thought I’d share several of these personal favorite Sublime 3 packages.

If you’re on Sublime 2, upgrade to Sublime 3, it’s totally stable.

To get started you’ll need to install Sublime Package Control into Sublime. It’s fairly simple, and the you’re read to go. The “Package Control: Install Package” command will now be available in your command pallet via Cmd+Shift+P or Ctrl+Shift+P.

SublimeLinter

SublimeLinterBase package for all linters. Syntax error highlighting can greatly reduce the save-run-revise cycle time. Most IDEs already have syntax error highlighting, why not add it to Sublime?

There are many SublimeLinter packages. Browse through them find what fits your workflow. Be sure to follow each packages setup instructions, each will be a bit different.

My personal must have’s are:

  1. SublimeLinter-phplint
  2. SublimeLinter-jshint
  3. SublimeLinter-jsxhint
  4. SublimeLinter-csslint
  5. SublimeLinter-contrib-scss-lint

BracketHighlighter

BracketHighlighterAn even better bracket highlighting than what comes with Sublime. It also shows starting and ending brackets in the gutter, and can matching for [ ], ( ), { }, ” “, ‘ ‘, <tag> </tag>.

SideBarEnhancments

Give the context menu more options when right clicking on files in a project. Duplicate files, move, rename, etc.

DocBlockr

DocBlockrEasier creation of document blocks for functions, classes, methods. It’s intelligent and looks ahead to see what you’re documenting to pre-fill the base info (such as input parameters and what is returned). Documenting is now convenient.

Pro tip: use the Tab key to navigate through the generated documented block, no need to click or use arrow keys.

Shell-Turtlestein

Launch the terminal/command line right in the context of your project directly from Sublime.  Either as a new window or as its own panel within sublime.

GitGutter

Visually shows the diff since the last commit in the gutter.  At a glance you can see what lines are additions, modifications, or deletions.

Origami

Split Sublime into multiple horizontal and vertical panes for side-by-side work. Remove the need to switch between tabs or windows as frequently when comparing files.

TrailingSpaces

Highlights and helps cleanup end of line trailing spaces. Nobody likes them right? Or maybe we just don’t notice them.

 

There are many other great packages out there for Sublime : code snippets, theme,  and syntax highlighting. But these are just some of my favorites.

A place for collecting my miscellaneous thoughts.