November 03, 2018 ReactJavascript

Introducing React-Scroll-To v2

The latest version of a React component I maintain just released, v2 of react-scroll-to. First, it started out as a component I needed, but over time a few people started using it. Because it was initially created for my specific use-case it started to show its warts when new features were ask for. The goals for v2 were two-part: introduce a more flexible API and implement some highly asked for features (scroll by a ref and smooth scrolling).

So what is react-scroll-to? React-scroll-to is a pretty simple component. It allows the control of scrolling either the brower's window, or a component (overflow) to a specific point.

We'll look at a few examples to show off what react-scroll-to can do. (As a note, in this post I'll only be showing render props, but react-scroll-to also supports higher order components. Examples can be found at: https://github.com/ganderzz/react-scroll-to)

Basics

import React, { Component } from "react";
import { ScrollTo } from "react-scroll-to";

export default class MyComponent extends Component {
  render() {
    return (
      <ScrollTo>
        {({ scrollTo }) => (
          <a onClick={() => scrollTo({ y: 500 })}>Scroll to Bottom</a>
        )}
      </ScrollTo>
    );
  }
}

In the component above we're importing the ScrollTo component from react-scroll-to. This is a render prop, so we'll pass a function as its children. ScrollTo's children has an object as its parameter--this is so the consumer of this component can choose, exactly, what properties they care about. Generally we'll only need scrollTo.

scrollTo() is a function, when called, will either:

  • Scroll the brower's window based on the given parameters (in this case, scroll 500px from the top of the page)
  • Scroll all <ScrollArea> components, inside <ScrollTo />, to the given parameters (We'll see this later)

Note: react-scroll-to uses absolute positions--the ability to use relative positioning is coming soon!

When a user clicks on the link, in the example, we'll see the window scroll down 500px!

Scroll Area

The <ScrollArea> component gives scrollTo the ability to scroll components, instead of the window.

import React, { Component } from "react";
import { ScrollTo, ScrollArea } from "react-scroll-to";

export default class MyComponent extends Component {
  render() {
    return (
      <ScrollTo>
        {({ scrollTo }) => (
          <>
            <a onClick={() => scrollTo({ y: 500 })}>Scroll to Bottom</a>

            <ScrollArea>My long content...</ScrollArea>
          </>
        )}
      </ScrollTo>
    );
  }
}

Since a <ScrollArea/> component lives as a child component of <ScrollTo />, whenever we call scrollTo(), it'll scroll all of the <ScrollArea /> components. So in this example when the link is clicked only the "My long content..." area will scroll.

But what if we have multiple <ScrollArea /> components?

import React, { Component } from "react";
import { ScrollTo, ScrollArea } from "react-scroll-to";

export default class MyComponent extends Component {
  render() {
    return (
      <ScrollTo>
        {({ scrollTo }) => (
          <>
            <a onClick={() => scrollTo({ y: 500 })}>Scroll to Bottom</a>

            <ScrollArea>My long content...</ScrollArea>

            <ScrollArea>My long content 2...</ScrollArea>
          </>
        )}
      </ScrollTo>
    );
  }
}

In the case where more than one <ScrollArea /> components exist in a <ScrollTo />, both components will scroll.

What if we only want to scroll one of the <ScrollArea /> components?

import React, { Component } from "react";
import { ScrollTo, ScrollArea } from "react-scroll-to";

export default class MyComponent extends Component {
  render() {
    return (
      <ScrollTo>
        {({ scrollTo }) => (
          <>
            <a onClick={() => scrollTo({ id: "content-two", y: 500 })}>
              Scroll to Bottom
            </a>

            <ScrollArea>My long content...</ScrollArea>

            <ScrollArea id="content-two">My long content 2...</ScrollArea>
          </>
        )}
      </ScrollTo>
    );
  }
}

By adding an id property to a <ScrollArea /> we are able to reference that component in our scrollTo() function. scrollTo() then takes another field, 'id', that'll scroll any <ScrollArea /> component that matches that id (id's must be unique).

V2 Features

scrollTo and ScrollArea have both existed in v1; let's look at branch new features.

Smooth Scrolling

Smooth scrolling couldn't be simpler. By adding a smooth: true property to the scrollTo() object, react-scroll-to will automatically apply smooth scrolling.

import React, { Component } from "react";
import { ScrollTo } from "react-scroll-to";

export default class MyComponent extends Component {
  render() {
    return (
      <ScrollTo>
        {({ scrollTo }) => (
          <a onClick={() => scrollTo({ x: 200, smooth: true })}>
            {/* Oh yeah, we can scroll by x also! */}
            Scroll to Bottom
          </a>
        )}
      </ScrollTo>
    );
  }
}
Scroll by Ref

Maybe instead of using a <ScrollArea /> component, we have a ref to a component we want to scroll. Or maybe instead we want to scroll a component outside <ScrollTo />'s children. Now we have the ability by providing the ref through the scrollTo() argument object!

import React, { Component } from "react";
import { ScrollTo } from "react-scroll-to";

export default class MyComponent extends Component {
  myRef = React.createRef();

  render() {
    return (
      <ScrollTo>
        {({ scrollTo }) => (
          <a onClick={() => scrollTo({ ref: this.myRef, y: 200, smooth: true })}>
             Scroll to Bottom
          </a>
        )}
      </ScrollTo>

      <div ref={this.myRef}>
        I'm outside ScrollTo!
      </div>
    );
  }
}

Conclusion

V2 of react-scroll-to provides a lot of behind-the-scenes structural changes that'll allow for a better developer experience while implementing new features. We also added many new features that have been in demand. As things solidify, we hope to expose hooks in react-scroll-to to allow even more flexibility.

Check it out: react-scroll-to Examples: Click Here