Skip to content

Instantly share code, notes, and snippets.

@jlongster
Last active February 8, 2018 16:14
Show Gist options
  • Star 41 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jlongster/f50f88da616a4d7b3032 to your computer and use it in GitHub Desktop.
Save jlongster/f50f88da616a4d7b3032 to your computer and use it in GitHub Desktop.
// 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 = ...;
this.node.appendChild(domElement);
}
removeItem: function(item) {
// 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)
}
};
// 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({
componentDidMount: function() {
this._view = new NonReactWidget();
},
render: function() {
return dom.ul(
null,
// Create a list of `Item` elements, they are stubs that let
// React do its diffing magic
dom.li(null, map(this.props.items, item => {
return Item({ item: item,
view: this._view });
}))
);
}
});
React.render(React.createElement(Items, { items: items }),
mountPoint);
@nishp1
Copy link

nishp1 commented Jun 17, 2015

First off, thanks for this, just when I needed it...

I did find one bug, this._view will throw error during render as it isn't instantiated until mount. I fixed that by tracking isMounted state, and only rendering children once component is mounted. In addition, I also added ability for parent to handle unmount as well incase just unmounting children wasn't good enough (common with jQuery plugins to free up listeners) at https://gist.github.com/nishp1/b3c9ac3d82603df4bf73.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment