Skip to content

How to Make Smooth Scroll to Multiple Sections with React useRef

My goal is to make smooth scroll. And move to multiple sections by clicking each buttons in React.

Here’s for those who want conclusion. Demo(CodePen)

Using ref and scrollIntoView

Declare Ref object with useRef and add ref to the scroll taget.

const targetRef = useRef<HTMLDivElement | null>(null);

<div ref={targetRef} />

Create handleClick and add it to the button.

const handleClick = () => {
  if (!targetRef.current) return;
  targetRef.current.scrollIntoView({ behavior: "smooth" });
};

<button className="gototop" type="button" onClick={handleClick}>
  Click
</button>

Smooth Scroll Demo(CodePen)

Smooth Scroll with Muiltple Sections

You need to create ref objects for each target.

This still work, but let’s clean up using map() .

// 🙅‍♀️
const targetRef1 = useRef<HTMLDivElement | null>(null);
const targetRef2 = useRef<HTMLDivElement | null>(null);
const targetRef3 = useRef<HTMLDivElement | null>(null);

Here’s the creating ref objects for each target.

const sectionNames: SectionProps[] = [
  {
    name: "Section 1",
  },
  {
    name: "Section 2",
  },
  {
    name: "Section 3",
  },
];

const sections = sectionNames.map((name) => {
  return {
    ...name,
    ref: useRef<HTMLDivElement>(),
  };
});

Then, create the buttons as scroll trigger using sections you created right now. You can also add ref object to the targets.

<nav className="nav">
  {sections.map((section) => (
    <a className="navItem" key={section.name} onClick={handleClick}>
      {section.name}
    </a>
  ))}
</nav>

{
  sections.map((section) => (
    <section className="container" key={section.name} ref={section.ref}>
      {section.name}
    </section>
  ));
}

And then, create multiple version of handleClick . You need to pass ref through props to specified which ref is the target.

const handleClick = (ref) => {
  if (!ref.current) return;
  ref.current.scrollIntoView({ behavior: "smooth" });
};

And now, you need modify onClick like this:

onClick={() => handleClick(section.ref)}

Here’s the multiple smooth scroll Demo. Demo(CodePen)

What I’ve learned

  • how to use useRef and ref object
  • smooth scroll in React

References