Skip to content

Instantly share code, notes, and snippets.

@milosdakic
Created September 26, 2017 06:26
Show Gist options
  • Save milosdakic/b96ce6e0bfb75ed0fec83292998eebf2 to your computer and use it in GitHub Desktop.
Save milosdakic/b96ce6e0bfb75ed0fec83292998eebf2 to your computer and use it in GitHub Desktop.
React Dynamic Component Renderer (with Feature Flags)

React Dynamic Component Renderer (with Feature Flags)

This is a simple implementation of a React dynamic component renderer. The aim here is to allow progresive rendering of React components onto a static HTML page/site. Usually used to sprinkle React components on top of an existing site.

Usage

The functionality has three main properties that need to be passed to the render method for this to work.

  1. node - this specifies which node the component should be mounted to
  2. component - the component thats being mounted
  3. features (optional) - determine based on features if this component should be mounted
import React from 'react'
import render from './render'
const HeaderProvider = () => (
<h1>SPA Provider mounted onto `.root` node.</h1>
)
const map = [
{ node: 'header', component: HeaderProvider },
]
render(map).subscribe(console.log('React mounted all providers.'))
import React from 'react'
import ReactDOM from 'react-dom'
import Rx from 'rx-lite-experimental'
import { has, get, every, some } from 'lodash'
/**
* const map = [
* {
* node: '.selector',
* component: ComponentProvider,
* features: {
* flags: { ADD_TO_CART: true },
* match: 'ALL' or 'SOME' or 'NONE'
* }
* },
* ]
*
* render(map).subscribe()
*/
const matcher = {
'ALL' : every,
'SOME' : some,
'NONE' : (c, p) => !every(c, p),
}
const flipper = [get(window, 'features', {})]
export default (map) =>
Rx.Observable.from(map)
.flatMap(item => Rx.Observable.if(
() => has(item, 'features'),
Rx.Observable.just(item)
.filter(({ features: { flags, match } }) => matcher[match](flipper, flags)),
Rx.Observable.just(item)
))
.filter(item => document.querySelector(item.node))
.flatMap(item =>
Rx.Observable.from(document.querySelectorAll(item.node))
.map(node => ({ node, component: item.component }))
)
.do(item => ReactDOM.render(React.createElement(item.component), item.node))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment