React
by samur3
HTML
<div id="app"></div>
CSS
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
.done {
color: rgba(0, 0, 0, 0.3);
text-decoration: line-through;
}
input {
margin-right: 5px;
}
React
const appRoot = document.getElementById('app');
class Reparentable extends React.Component<{ el: HTMLElement }> {
this.ref = React.createRef();
componentDidMount() {
this.ref.current!.appendChild(this.props.el);
}
render() {
return <div ref={this.ref}/>;
}
}
class Parent extends React.Component {
private readonly childContainer: HTMLElement = document.createElement('div');
state = {
down: false,
};
handleClick = () => {
this.setState(prevState => ({
down: !prevState.down
}));
}
render() {
return (
<div>
<p>Down: {this.state.down + ''}</p>
<button onClick={this.handleClick}>Click</button>
{ReactDOM.createPortal(<Child />, this.childContainer)}
<h2>Root 1</h2>
<div key="1">
{!this.state.down && <Reparentable el={this.childContainer} />}
</div>
<h2>Root 2</h2>
<div key="2">
{this.state.down && <Reparentable el={this.childContainer} />}
</div>
</div>
);
}
}
class Child extends React.Component {
componentDidMount() {
console.log('componentDidMount');
}
componentWillUnmount() {
console.log('componentWillUnmount');
}
render() {
return (
<div>
CHILD
</div>
);
}
}
ReactDOM.render(<Parent />, appRoot);