This is a Backbone integration HOC based on my approach to integrating React, MobX, and Backbone from a few months ago. It takes away all the integration boilerplate and lets you focus on the important stuff – setting data for the old Backbone View and potential rendering embellishments.

The same approach should work with any component-based library like Preact, Inferno, and Vue, but I haven't tried yet.

So how does this work? How did a HOC replace 25 lines of JavaScript with a single @backbone(ToolboxView) decorator? Let me show you.

How HOCses Improve Your Code

The first step is to take everything generic out of your component and put it into a new one. This will be what your HOC does.

If you can't tell what's generic, wait until you have two components that look similar. Any boilerplate they share is a good candidate for a HOC.

In our example that boilerplate is:

the constructor that sets up autorun

functions keeping Backbone and React render in sync

all the Backbone rendering things

an anchor element for Backbone to hook into

Soooo… everything.

We're leaving React's render() method out of the HOC to give consumers better flexibility, and we're adding the ability to set Backbone params. Those are important.

constructor sets up autorun so our component can react to MobX store changes. This automatically turns our Backbone'd components into observers, but I like to include the @observer call when using them anyway. Helps with readability

The componentDidMount, componentDidUpdate, and componentWillUnmount methods ensure our Backbone View gets rendered, re-rendered, and cleaned up when appropriate. Each method includes a hook for users of our HOC to add their own lifecycle logic. I haven't really had a use for this yet, but I think it's a good idea to have.

_init, _render, and _cleanup handle the actual Backbone stuff. They're helper methods that make it easier to reuse bits in different React lifecycle methods.

get anchor is like a render() method but not. We could render here, but that would reduce flexibility. Instead, we give consumers an easy way to render the Backbone anchor point wherever.

Step 2: Making It a HOC

To turn this component into a real HOC, we have to wrap it in a function. You could call this function an class factory because that's what it is. It creates classes.

function (WrappedComponent) {
return // code from above
}

Yep, a function that takes a component to be wrapped and returns a class extending said component. That really is it.

Congratulations, you have made a HOC.

Caveat: We use super when to invoke a method on the parent class – the wrapped component – and this when we access instance properties even if they are defined on the parent. Both your wrapped component and your HOC core component share the same this reference.

Step 3: Adding More Arguments

Now here's a tricky part. Adding more arguments – like which Backbone View to wrap with – requires currying. At least it does if you want to use your HOC as a decorator like I did.

Currying means that instead of having functions with multiple arguments, we create a composition of single-argument functions. I'm not entirely certain why currying is all the rage, but it makes many approaches to functional programming easier to use.

backboneProps lets us define parameters fed into the Backbone View – the HOC accesses them as this.backboneProps.

Inside render(), we use this.anchor anywhere we want to place the anchor point for our Backbone View. In this case, we're rendering just that, but in others, we might want to wrap it with useful markup that makes it look better in its new context.

Conclusion

HOCs are great, and I wish I started using them earlier. There's definitely going to be a chapter about HOCses in the new version of React+D3. Some prime targets for this stuff in there.

And yes, you can use them without decorators. It's just not as pretty. Something like this: