Skip to content

Instantly share code, notes, and snippets.

@leoasis leoasis/01.js
Last active Jun 26, 2017

Embed
What would you like to do?
Reparenting a component
import React, { Component } from 'react';
import PropTypes from 'proptypes';
import ReactDOM from 'react-dom';
const store = {};
function getMountNode(uid) {
if (!store[uid]) {
store[uid] = {
mountNode: document.createElement('div'),
inUse: true
};
} else {
store[uid].inUse = true;
}
return store[uid].mountNode;
}
function removeMountNode(uid) {
const record = store[uid];
record.inUse = false;
setTimeout(() => {
if (!store[uid].inUse) {
ReactDOM.unmountComponentAtNode(store[uid].mountNode);
delete store[uid];
}
}, 0);
}
export default class Reparentable extends Component {
static propTypes = {
uid: PropTypes.string.isRequired,
children: PropTypes.element.isRequired
}
componentDidMount() {
const mountNode = getMountNode(this.props.uid);
this.el.appendChild(mountNode);
this.renderChildrenIntoNode(mountNode);
}
componentDidUpdate() {
const mountNode = getMountNode(this.props.uid);
this.renderChildrenIntoNode(mountNode);
}
componentWillUnmount() {
removeMountNode(this.props.uid);
}
renderChildrenIntoNode(node) {
// We use this instead of `render` because this also handles
// passing the context
ReactDOM.unstable_renderSubtreeIntoContainer(this, this.props.children, node);
}
render() {
return <div ref={(el) => { this.el = el; }}></div>;
}
}
<div>
{this.state.showingPage === 'page1' &&
<Page1>
<Reparentable uid="1">
<FooComponent {…someProps} />
</Reparentable>
</Page1>}
{this.state.showingPage === 'page2' &&
<Page2>
<Reparentable uid="1">
<FooComponent {…someOtherProps} />
</Reparentable>
</Page2>}
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.