• import React, { Component } from "react";
  • import PropTypes from "prop-types";
  • ScrollTo.jsx
    class ScrollTo extends Component {
  •   constructor(props) {
  •     super(props);
  • ScrollTo is a parent component that will keep track of all ScrollArea components that gets mounted
        this.scrollArea = [];
  •     this.handleScroll = this.handleScroll.bind(this);
  •   }
  •   getChildContext() {
  •     return {
  • This function will get called from ScrollArea when it gets mounted
          addScrollArea: ref => {
  •         this.scrollArea = this.scrollArea.concat(ref);
  •       },
  • This function will get called from ScrollArea when it gets unmounted
          removeScrollArea: ref => {
  •         this.scrollArea = this.scrollArea.filter(container => {
  •           return container !== ref;
  •         });
  •       }
  •     };
  •   }
  •   handleScroll(x, y) {
  • If there are no ScrollArea's present, we will scroll the entire window
        if (this.scrollArea.length === 0) {
  •       scrollWindow(x, y);
  •     } else {
  • Otherwise, we will scroll each ScrollArea
          this.scrollArea.forEach(container => {
  •         container.scrollLeft = x;
  •         container.scrollTop = y;
  •       });
  •     }
  •   }
  •   render() {
  • This uses the render prop pattern. All children of ScrollTo will have access to the "this.handleScroll" function
        return this.props.children && this.props.children(this.handleScroll);
  •   }
  • }
  • ScrollTo.childContextTypes = {
  •   addScrollArea: PropTypes.func.isRequired,
  •   removeScrollArea: PropTypes.func.isRequired
  • };
  • ScrollArea.jsx
    class ScrollArea extends Component {
  •   componentDidMount() {
  • Adds a reference of itself to the parent ScrollTo component
        this.context.addScrollArea(this.node);
  •   }
  •   componentWillUnmount() {
  • Removes the reference of itself from the parent ScrollTo component
        this.context.removeScrollArea(this.node);
  •   }
  •   render() {
  •     const { children, ...props } = this.props;
  •     return (
  •       <div {...props} ref={node => (this.node = node)}>
  •         {children}
  •       </div>
  •     );
  •   }
  • }
  • ScrollArea.contextTypes = {
  •   addScrollArea: PropTypes.func.isRequired,
  •   removeScrollArea: PropTypes.func.isRequired
  • };
  • A simple wrapper around window.scroll
    function scrollWindow(x = 0, y = 0) {
  •   window.scroll(x, y);
  • }