There are a lot of live projects out there built using older web tech stacks. Starting from scratch is usually out of the question and upgrading the codebase could be a herculean task, especially if there are no unit tests or decent build tools already in place. This article discusses and demonstrates a simple working demo of integrating a Backbone/jQuery app with React by using Redux and the Ducks++ pattern. If you haven’t heard of Ducks, it is basically a simple design pattern for modularising your Redux code.
A live working demo can be found at CodePen, and the entire project is also available on GitHub. The app demonstrates two switches: one is implemented using Backbone/jQuery, and the other is implemented in React; however both are synced through the backbone model and the Redux store. The React code is bundled up and dropped into the legacy app — effectively, it is an immediately invoked function expression and behaves like a library.
The legacy app remains in the driving seat and is responsible for building and mounting the React code:
var reactToggleApp = window.reactModule.make({el: document.getElementById('react-module')});
reactToggleApp.render();
The React code is available through a factory function, which is globally available. This allows us to pass in necessary callbacks and options, e.g. an error handling mechanism or translation function. The React module also needs a DOM element to mount to. After running the factory function, an object with the following interface will be returned:
{render,destroy,store,ducks}
Render and destroy allow the parent app to initiate and remove the react app. The Redux store and the ducks modules are the key to allowing synchronisation between the two worlds.
The factory function exposes the Redux store, which allows us to subscribe to any change in the store and propagate those changes to the Backbone models. Similarly, changes to the backbone models can be propagated to the Redux store by dispatching the appropriate action. The trick to achieving this, is by following the Ducks++ pattern, which bundles up the actions and selectors. Notice in the code below, we are synching the attribute on
of a Backbone model to the toggle
attribute of the keyValues
Duck using its actionCreators
and selectors
.
model.on('change:on', function (model, value) {window.reactModule.store.dispatch(window.reactModule.ducks.keyValues.actionCreators.setValue('toggle', value));});
window.reactModule.store.subscribe(function() {var state = window.reactModule.store.getState();var value = window.reactModule.ducks.keyValues.selectors.getValue(state, 'toggle');
model.set('on', value);});
We now have the ability to replace legacy components with react modules and eventually replace all the legacy code.
This approach is surprisingly straight forward, considering we are merging a brand new codebase to a legacy system. We can even implement the React code in a separate repository and treat it like a greenfield project — and lets face it, who doesn’t want to work on Greenfield!?
Remember if you would like to experiment with the code presented in this article, feel free to clone/fork my repo.
If you found this article useful/inspiring tap the 💚 so others can enjoy it, too.