Skip to content

Instantly share code, notes, and snippets.

@nishp1
Forked from jlongster/smart-wrapper.js
Last active February 8, 2018 16:14
Show Gist options
  • Save nishp1/b3c9ac3d82603df4bf73 to your computer and use it in GitHub Desktop.
Save nishp1/b3c9ac3d82603df4bf73 to your computer and use it in GitHub Desktop.
const React = require('react');
// Have some complicated non-React widgets that manipulate DOM?
// Do they manage a list of DOM elements? Here's how to wrap it
// into a React component so you can "constantly rerender" it.
// A dumb non-react widget that manually manage some DOM node that
// represent a list of items
function NonReactWidget(node) {
this.node = node;
}
NonReactWidget.prototype = {
addItem: function(item) {
// construct a DOM element representing the item
var domElement = document.createElement('div');
domElement.innerHTML = item.name;
this.node.appendChild(domElement);
},
removeItem: function(item) {
// if widget is destroyed, just return
if (this.isDestroyed) { return; }
// remove the item from the list (need to find it somehow)
},
updateItem: function(item) {
// update the item in the list (need to find it and figure out how
// to update it, there's probably constraints here already since
// you weren't using React). You might even be able to just ignore
// this (with my use case I can, nothing is ever updated)
},
destroy: function () {
this.isDestroyed = true;
// remove all items
}
};
// A React interface. We don't want to carefully call
// `addItem`/`removeItem` ourselves, we want to throw an array of
// items at it like we would with React components. The `Item`
// component is a stub that works with React's vdom system but gives
// us lifecycle events to actually propagate the change into the DOM.
const Item = React.createClass({
componentDidMount: function() {
this.props.view.addItem(this.props.item);
},
componentWillUnmount: function() {
this.props.view.removeItem(this.props.item);
},
componentWillReceiveProps: function(nextProps) {
this.props.view.updateItem(nextProps.item);
},
render: function() {
return null;
}
});
const Items = React.createClass({
getInitialState() {
// need to keep track of isMounted state so that child components are only rendered after
// giving them access to `view`
return { isMounted: false };
},
componentDidMount() {
this._view = new NonReactWidget(this.refs.node.getDOMNode());
this.setState({ isMounted: true });
},
componentWillUnmount() {
this._view.destroy();
},
render: function() {
return (
<ul ref="node">
{
this.state.isMounted && this.props.items.map((item) => {
return <Item item={ item } view={ this._view } />
})
}
</ul>
);
}
});
const items = [{
id: 1,
name: 'Item One'
}, {
id: 2,
name: 'Item two'
}];
React.render(<Items items={ items } />, document.getElementById('main'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment