Skip to content
This repository was archived by the owner on Sep 21, 2022. It is now read-only.

Commit dd04740

Browse files
committed
Add WithLayout component for delightful pre-rendering.
1 parent ba5a275 commit dd04740

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

04 - Layout/05 - Pre Rendering.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import React, { Component } from 'react';
2+
import ReactDOM from 'react-dom';
3+
4+
let preRenderCache = new WeakMap(); // Could be state instead?
5+
let measure = document.createElement('div');
6+
7+
export default class WithSize extends Component {
8+
componentDidMount () {
9+
// If we don't have the item in cache yet, render it.
10+
if (!preRenderCache.has(this.props.data)) {
11+
// Append a temporary node to the dom to measure it.
12+
document.body.appendChild(this.measure);
13+
14+
// Render the child and append it to the node.
15+
let child = this.props.children();
16+
let rendered = ReactDOM.render(child, this.measure);
17+
18+
// Take the measurement and remove the temporary node from the dom.
19+
let {clientWidth, clientHeight} = rendered;
20+
document.body.removeChild(this.measure);
21+
22+
// Process layout using the prop function, and force render.
23+
let processedLayoutInfo = this.props.processLayout(this.props.data, clientWidth, clientHeight);
24+
preRenderCache.set(this.props.data, this.props.children(processedLayoutInfo));
25+
this.forceUpdate();
26+
}
27+
}
28+
29+
render () {
30+
let renderedItem = preRenderCache.get(this.props.data);
31+
if (renderedItem) {
32+
return renderedItem;
33+
}
34+
35+
// Return nothing until we're ready to render.
36+
return null;
37+
}
38+
}
39+
40+
WithSize.propTypes = {
41+
children: React.PropTypes.func,
42+
data: React.PropTypes.object,
43+
processLayout: React.PropTypes.func,
44+
};
45+
46+
47+
// Usage looks like:
48+
class DynamicList extends Component {
49+
processLayout(width, height) {
50+
return {
51+
top, left, bottom, right
52+
};
53+
}
54+
55+
render () {
56+
return (
57+
<div>
58+
{this.props.items.map((item, idx) =>
59+
<WithSize data={item} key={idx} processLayout={this.processLayout.bind(this)}>
60+
{
61+
(position={left: 0, top: 0}) => <div style={{top: position.top, left: position.left}}>...</div>
62+
}
63+
</WithSize>
64+
)}
65+
</div>
66+
);
67+
}
68+
}

0 commit comments

Comments
 (0)