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
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
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
recompose as well as state management via
lifecycle and mixing another data source from
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!