The product I am enthusiastically working on - Navigo3 - was historically written as combination of XSLT and JSP. Do you remember XSLT?
Short time before I joined it it was decided that is should be remade in React.js. It was great decision but transition is not that easy.
Because Navigo3 is in production usage we have to transform from XSLT to React step by step. Some pages are that complex that it would be handy being able to combine XSLT and React on single page. Typically it is required on pages that combine many types of information - dashboards. A few graphs, tables, list of tasks, … It would be hard to rewrite all at glance. But rewrite each one is quite simple.
At the same time we have new pages which are written completely in React and uses hashtag navigation. In main entry file index.js there is redux-router hierarchy and it expects that it runs on purely React page. This actually does not match with demand to embed some components into JSP/XSLT static page with classical URL navigation, right?
But I would like to share React components between brand new react pages and legacy XSLT pages! And at some moment just compose React page from existing components and abandon legacy ones. So how to do that?
That’s it. Lets sum up some advantages:
React.js FTW!
Here is sample of indexLegacy.js
//libraries
import React from "react"
import {render} from "react-dom"
import moment from "moment"
import jQuery from 'jquery'
import {Utils} from './utils/Utils'
//container for legacy components
import {LegacyApp} from './containers/LegacyApp'
import {ReactDemo} from './quark/ReactDemo'
//...and other 10+ components
//key is CSS selector, value is function that returns React element
const instances = {
'.hack_react_demo': (elem)=><ReactDemo/> //this defines method that creates React component for HTML element <div class='hack_react_demo'/> placed everywhere
//...and other 10+ components
}
//render reactElement into DOM elemenet wrapped by LegacyApp function
__createReactInstance(element, reactElement) {
render(<LegacyApp>{reactElement}</LegacyApp>, element)
}
//for each entry in instances object
Object.keys(instances).forEach(selector=>{
//for each DOM element found by jQuery
jQuery(selector).each((i, element)=>{
//get function for selector and call it (passing DOM element)
const reactElement = instances[selector](element)
//create React component
__createReactInstance(element, reactElement)
})
})
ReactDemo.js:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
export class ReactDemo extends Component {
render() {
return <div>
Hi, Stereo!
</div>
}
}
LegacyApp.js:
import React, {Component} from "react";
import PropTypes from 'prop-types'
export class LegacyApp extends Component {
static childContextTypes = {
//define some context for child pages - app settings, etc.
}
getChildContext() {
return {
//place context here
};
}
render() {
return <div>
{this.props.children}
</div>
}
}
Fragment of JSP page:
<div class='hack_react_demo'></div>