Skip to content

Instantly share code, notes, and snippets.

@tbranyen
Last active May 3, 2017 05:39
Show Gist options
  • Save tbranyen/66a3223e234ad4d12518f60843a1ab3d to your computer and use it in GitHub Desktop.
Save tbranyen/66a3223e234ad4d12518f60843a1ab3d to your computer and use it in GitHub Desktop.
Consume a DOM Node in React
{
const { Component, cloneElement, createElement: jsx } = React;
const { findDOMNode, render } = ReactDOM;
const map = new WeakMap();
const attrMap = {
htmlFor: 'for',
className: 'class',
};
const toReactElement = (domNode, props) => {
const ref = node => {
const parentNode = node && node.parentNode;
if (parentNode) {
parentNode.replaceChild(domNode, node);
}
else if (!node) {
domNode.parentNode.removeChild(domNode);
}
};
const setProps = (domNode, props = {}) => {
const propNames = Object.keys(props);
for (let i = 0; i < propNames.length; i++) {
const propName = propNames[i];
const attrName = attrMap[propName] || propName;
domNode.setAttribute(attrName, props[propName]);
}
};
if (map.has(domNode)) {
setProps(domNode, props);
return cloneElement(map.get(domNode), props);
}
const instance = jsx(class extends Component {
render() {
return jsx(domNode.nodeName.toLowerCase(), { ref });
}
shouldComponentUpdate() {
return false;
}
});
setProps(domNode, props);
map.set(domNode, instance);
return instance;
}
const someDomNode = Object.assign(document.createElement('video'), {
src: 'test'
});
class App extends Component {
render() {
return jsx('div', null, toReactElement(someDomNode, this.state));
}
constructor(props) {
super(props);
this.state = { src: 0 };
}
componentDidMount() {
setInterval(() => {
this.setState({ src: ++this.state.src });
console.log(findDOMNode(this).querySelector('video') === someDomNode);
}, 1000);
}
}
ReactDOM.render(jsx(App), document.body.querySelector('main'));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment