Web Log of Ross Chapman

Web Log of Ross Chapman

Too many imports, eyes tired

There are too many imports in this React component file. I’m staring down like 50 lines of imports. External libraries (React, Lodash, etc…), our own internal libraries, components files, helpers, constants. The last bothers me the most because they feel like implementation details I want hidden away in these other components or helpers. So I’m looking at this statement inside a render() block:

const isSoldOut = this.props.statusType == SOLD_OUT;

And suddenly I’m reminded of what Kyle Simpson told me on twitter a couple weeks ago:

“in ‘functional programming,’ we love and embrace functions! functions everywhere!” – @getify

That’s it, that’s my out. We can refactor the equality expression into a function that represents data:

const isSoldOut = ({ status }) => status === SOLD_OUT;

We might find our code getting repetitive for computing different statuses:

const isSoldOut = ({ status }) => status === SOLD_OUT;
const isAvailable = ({ status }) => status !== UNAVAILABLE && status !== SOLD_OUT; 
const isUnavailable = ({ status }) => status !== UNAVAILABLE; 
// etc...

In which case we might find an indirection at a higher level that hides the implementation details of our equality expressions:

const getTicketStatusType = (ticketProps) => STATUS_TYPES_MAP[get(ticketProps, "status")];

STATUS_TYPES_MAP could implement an object hash where the equality expressions are values or our data functions.

Well, in the end I may not be decreasing the total number of imports by much, I’m perhaps doing a few other useful things:

  • Cutting down the number of imports from different files
  • Creating a reusable abstraction – which I know can be employed elsewhere
  • De-cluttering render() which makes integration tests simpler, possibly unnecessary for some cases since logic can be independently unit tested

That last point is important. At least to me. Untidy render() blocks are hard to scan, debug, and test. The machinations for constructing and composing the things to render can happen in other places: above the component class definition, in class methods, or in a separate file. The first options is one I quite like because abstractions don’t have to be all that general. It’s great if they are localized to the component at hand.