-
-
Save nishp1/b3c9ac3d82603df4bf73 to your computer and use it in GitHub Desktop.
This file contains 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
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