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.
In an example:
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.
Conclusion
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!