Skip to content

Instantly share code, notes, and snippets.

@okonet
Created January 13, 2017 18:19
Show Gist options
  • Save okonet/2a340aa572f9beaf2471a7bc100c2a1d to your computer and use it in GitHub Desktop.
Save okonet/2a340aa572f9beaf2471a7bc100c2a1d to your computer and use it in GitHub Desktop.
React at 60fps Example 3
export default class ScrollPane extends Component {
static contextTypes = {
registerPane: PropTypes.func.isRequired,
unregisterPane: PropTypes.func.isRequired
};
componentDidMount() {
this.context.registerPane(this.el)
}
componentWillUnmount() {
this.context.unregisterPane(this.el)
}
render() {
return (
<div ref={(el) => { this.el = el }}>
{this.props.children}
</div>
)
}
}
export default class ScrollContainer extends Component {
static childContextTypes = {
registerPane: PropTypes.func,
unregisterPane: PropTypes.func
}
getChildContext() {
return {
registerPane: this.registerPane,
unregisterPane: this.unregisterPane
}
}
panes = []
registerPane = (node) => {
if (!this.findPane(node)) {
this.addEvents(node)
this.panes.push(node)
}
}
unregisterPane = (node) => {
if (this.findPane(node)) {
this.removeEvents(node)
this.panes.splice(this.panes.indexOf(node), 1)
}
}
addEvents = (node) => {
node.onscroll = this.handlePaneScroll.bind(this, node)
}
removeEvents = (node) => {
node.onscroll = null
}
findPane = node => this.panes.find(pane => pane === node)
handlePaneScroll = (node) => {
window.requestAnimationFrame(() => {
// Calculate new scrollTop positions
// for left and right panes based on
// DOM nodes and evt.target.scrollTop
// and set it directly on DOM nodes
this.panes.forEach((pane) => {
pane.scrollTop = …
})
})
}
render() {
return (
<div>
<ScrollPane>
<ExpensiveComponent />
</ScrollPane>
<ScrollPane>
<ExpensiveComponent />
</ScrollPane>
</div>
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment