react-components
Version:
React components used by Khan Academy
70 lines (59 loc) • 2.19 kB
JSX
/* Create a new "layer" on the page, like a modal or overlay.
*
* const LayeredComponent = React.createClass({
* mixins: [LayeredComponentMixin],
* render: function() {
* // render like usual
* },
* renderLayer: function() {
* // render a separate layer (the modal or overlay)
* }
* });
*
* From http://jsfiddle.net/LBAr8/
*/
const React = require('react');
const ReactDOM = require("react-dom");
const LayeredComponentMixin = {
componentDidMount: function() {
// Appending to the body is easier than managing the z-index of
// everything on the page. It's also better for accessibility and
// makes stacking a snap (since components will stack in mount order).
this._layer = document.createElement('div');
document.body.appendChild(this._layer);
this._renderLayer();
},
componentDidUpdate: function() {
this._renderLayer();
},
componentWillUnmount: function() {
this._unrenderLayer();
document.body.removeChild(this._layer);
},
_renderLayer: function() {
// By calling this method in componentDidMount() and
// componentDidUpdate(), you're effectively creating a "wormhole" that
// funnels React's hierarchical updates through to a DOM node on an
// entirely different part of the page.
const layerElement = this.renderLayer();
// Renders can return null, but React.render() doesn't like being asked
// to render null. If we get null back from renderLayer(), just render
// a noscript element, like React does when an element's render returns
// null.
if (layerElement === null) {
ReactDOM.render(<noscript />, this._layer);
} else {
ReactDOM.render(layerElement, this._layer);
}
if (this.layerDidMount) {
this.layerDidMount(this._layer);
}
},
_unrenderLayer: function() {
if (this.layerWillUnmount) {
this.layerWillUnmount(this._layer);
}
ReactDOM.unmountComponentAtNode(this._layer);
},
};
module.exports = LayeredComponentMixin;