Skip to content

Instantly share code, notes, and snippets.

@resistdesign
Last active June 16, 2016 06:42
Show Gist options
  • Save resistdesign/16230bc92b13b72e3b429341b757678b to your computer and use it in GitHub Desktop.
Save resistdesign/16230bc92b13b72e3b429341b757678b to your computer and use it in GitHub Desktop.
A simple React Flux implementation with Dependency Injection for Components created by a React Router createElement handler.
import React, { Component } from 'react';
export default class FluxDI {
static validateContextName(name){
if(typeof name !== 'string'){
throw new Error('`name` must be a string.');
}
}
static validateContext(context){
if(!(context instanceof Map)){
throw new Error('`context` must be a Map.');
}
}
contexts = {};
constructor(contexts){
if(contexts instanceof Object){
this.contexts = contexts;
}
}
ensureContexts(){
if(!(this.contexts instanceof Object)){
this.contexts = {};
}
}
getContext(name){
FluxDI.validateContextName(name);
this.ensureContexts();
if(!(this.contexts[name] instanceof Map)){
const newContexts = { ...this.contexts };
newContexts[name] = new Map();
this.contexts = newContexts;
}
return this.contexts[name];
}
setContext(name, context){
FluxDI.validateContextName(name);
FluxDI.validateContext(context);
this.ensureContexts();
const newContexts = { ...this.contexts };
newContexts[name] = context;
}
removeContext(name){
FluxDI.validateContextName(name);
this.ensureContexts();
const newContexts = { ...this.contexts };
delete newContexts[name];
this.contexts = newContexts;
}
cloneMap(map){
if(map instanceof Map){
const newMap = new Map();
map.forEach((value, key) => {
newMap.set(key, value);
});
return newMap;
}
}
/**
* Add a component to a context.
*/
addComponent(contextName, component, props, serviceMap, eventMap, immediateMap, contextPropMap){
const context = this.getContext(contextName);
const getComponent = (ViewComponent, contextProps) => {
if(component instanceof Function){
const initialState = { ...props };
if(contextPropMap instanceof Object && contextProps instanceof Object){
for(const k in contextPropMap){
if(contextPropMap.hasOwnProperty(k)){
const targetProp = contextPropMap[k];
if(contextProps.hasOwnProperty(targetProp)){
initialState[k] = contextProps[targetProp];
}
}
}
}
class FluxDIComponent extends Component {
constructor(){
super();
}
componentDidMount(){
if(serviceMap instanceof Object){
const newState = {};
if(eventMap instanceof Object){
for(const k in eventMap){
if(eventMap.hasOwnProperty(k)){
const targetProp = eventMap[k];
const serviceMethod = serviceMap[targetProp];
if(serviceMethod instanceof Function){
newState[k] = async (...args) => {
const data = await serviceMethod.apply(null, args);
const updatedState = {};
updatedState[targetProp] = data;
this.setState(updatedState);
};
}
}
}
}
if(immediateMap instanceof Object){
for(const k in immediateMap){
if(immediateMap.hasOwnProperty(k)){
const callWith = immediateMap[k];
const args = callWith instanceof Function ? callWith(contextProps) : [ ...(callWith || []) ];
const serviceMethod = serviceMap[k];
if(serviceMethod instanceof Function){
const immediateCall = async () => {
const data = await serviceMethod.apply(null, args);
const updatedState = {};
updatedState[k] = data;
this.setState(updatedState);
};
immediateCall();
}
}
}
}
this.setState(newState);
}
}
state = initialState;
render(){
return (
<ViewComponent
{ ...this.state }
/>
);
}
}
return FluxDIComponent;
}
};
context.set(component, getComponent);
}
/**
* Remove a component from a context.
*/
removeComponent(contextName, component){
const context = this.getContext(contextName);
const newContext = this.cloneMap(context);
newContext.unset(component);
this.setContext(contextName, newContext);
}
/**
* Get a FluxDI component.
*/
getComponent(contextName, component, props){
const context = this.getContext(contextName);
const getComponent = context.get(component);
if(getComponent instanceof Function){
const FluxDIComponent = getComponent(component, props);
return (
<FluxDIComponent/>
);
}else{
return (
<component
{ ...props }
/>
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment