Building Reactive Props with Meteor and Recompose

This is a follow up to my post: Building HOCs with Recompose

The narrative continues:

So at Workpop, we’re continually refactoring and moving away from some core Meteor paradigms ushering the new world of GraphQL and NON-realtime interfaces. As we build features we are picking patterns from the broader JS community rather than the “Meteor” way. This has proven to be so successful for both the morale of the development team AND the sanity of our code. Less magic and more control.

But, as any engineer knows, you can’t rebuild Rome in one day. Given we were building things in a HOC/Enhancer pattern we needed Meteor’s reactivity to fit into legacy parts of our codebase still depending on that reactivity e.g. (User document changes, Payment/Subscription changes, Notifications)

Meteor does ship createContainer which worked before we jumped on the Recompose bandwagon, but once we drank the koolaid of that #containerLYFE, it became more of annoyance. createContainer, in my opinion, is hard to compose with other Recompose HOCs. We wanted a HOC that would fit the pattern and style of other UI components.

Today, I’m going to show you how you can make a reactive HOC with Recompose and some Meteor magic. Let’s begin:

First things first, we create a Higher order function that returns a BaseComponent. If you haven’t noticed by now, this is pretty much how every Higher Order Component is usually built.

Our HOC here takes a propFn, this will be exactly the same function you would give createContainer. Make sure to return an Object in the propFn. Because this pattern returns props, I thought it would be fit to name similarly to withProps and name the HOC withReactiveProps.

Alright cool, we’re all squared away with the basic HOC boilerplate. Let’s do some cool stuff now.

First off, I know what you’re thinking. MIXINS? THIS ASSHOLE JUST BUSTED OUT MIXINS? Well people, we need to think about the economics of the situation. Do I want to be responsible for refactoring ReactMeteorData? HELL NO. So roll with punches.

Let’s point out the interesting thing we’re doing here. Notice how I imported createEagerFactory from recompose? When higher-order components render functional components, we do not get benefits of lazy evaluation. We use createEagerFactory to check if the BaseComponent is an expression that always evaluates to the SAME result in ANY context. If it does, rather than returning a React element, it calls the functional component with the given props and returns its output. I picked this style up from Andrew Clark and still exploring its advantages! Comment below your thoughts too!

Alright let’s continue:

So now we render a React Component via createClass, this is because we need to support mixins. We follow the ReactMeteorData’s API and attach a getMeteorData function that calls our propFn with the Component’s props.

Imagine we are looking at all of our paying users and as the customerId changes, we want to display different customer info from our Mongo Collections.

I like this example because it combines react-redux's connect with recompose as well as state management via lifecycle and mixing another data source from minimongo.

First, we connect our component to the Redux store for a given selector.

Then in our lifecycle hooks we manage the dispatch of an Action Creator that will deal with the Customer profile state.

Finally, as the customerId changes, we subscribe to the new customer, query minimongo for the document and bind the results as props to the Component.

Bam, Meteor + Recompose + Redux all playing along nicely.

Recompose is great at enforcing patterns in HOC development. You can take its principles and build your own HOCs for any situation! Comment below if you like this approach and let’s keep coding. Thanks!

Software Engineer at Workpop, Inc.