Last active
September 5, 2016 14:15
-
-
Save butchler/e0a6b47cb94126ab89352d9e04ad0e43 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Children, createElement } from 'react'; | |
export function replaceRenderedComponents(mappings) { | |
let componentMap; | |
if (mappings instanceof Map) { | |
componentMap = mappings | |
} else if (Array.isArray(mappings)) { | |
componentMap = new Map(mappings); | |
} else { | |
throw new Error('Expected Map or array of pairs'); | |
} | |
const replace = getReplacer(componentMap); | |
return component => { | |
let wrapper; | |
if (component.prototype.isReactComponent) { | |
wrapper = class Wrapper extends component { | |
render() { | |
const output = super.render(); | |
return replace(output); | |
} | |
}; | |
} else if (typeof component === 'function') { | |
wrapper = (props) => { | |
const output = component(props); | |
return replace(output); | |
}; | |
} else { | |
throw new Error('Expected React component'); | |
} | |
wrapper.displayName = `replaceRenderedComponents(${component.displayName || component.name})`; | |
return wrapper; | |
}; | |
} | |
function getReplacer(componentMap) { | |
const replace = element => { | |
if (!element) { | |
return null; | |
} | |
let type; | |
if (componentMap.has(element.type)) { | |
type = componentMap.get(element.type); | |
} else { | |
type = element.type; | |
} | |
const children = Children.map(element.children, replace); | |
return createElement(type, element.props, children); | |
}; | |
return replace; | |
} | |
/** | |
* This is probably a bad idea, but it was interesting to write. | |
* | |
* Usage: | |
* | |
* ``` | |
* import ParentComponent from 'components/parent'; | |
* import ChildComponent from 'components/child'; | |
* import ChildContainer from 'containers/child'; | |
* | |
* const replace = replaceRenderedComponents([ | |
* [ChildComponent, ChildContainer], | |
* ]); | |
* | |
* export default connect(mapState, mapDispatch)(replace(ParentComponent)); | |
* ``` | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment