How to scroll to a certain point in React apps

black screen with code

In traditional web page development, developers would use anchor tags and id to navigate to a certain part of a web page. While you can still add this approach to a component-based React application, you may need more code to have certain effects such as smoothly scrolling to the target point on the page. But there is a much better way to do this in React.

React refs and useRef hook.

React refs is a way to access different elements(DOM nodes) of the page by creating a reference point. I this post,I will show you how to smoothly scroll to a certain point on a single page app with useRef hook.

Step 1: create a React App

Create a React app with create-react-app

Erase the default App.js code and replace it with the following code.

import React from 'react';
import './App.css';

export default function App() {
	return (
    <div>
        <ul className='main-menu'>
          <div>HOME</div>
          <div>ABOUT</div>
          <div>CONTACT</div>
        </ul>
        <Home/>
        <About/>
        <Contact/>      
    </div>
  )
}

const Home = () => (
    <div className="home"></div>
)

const About = () => (
    <div className="about"></div>
)

const Contact = () => (
    <div className="contact"></div>
)

Note that there are three components in this app.

What we are going to do is to make reference points to these components and smoothly scroll when the user clicks on the main menu on the header.

Add CSS code below to the App.css file

.main-menu{
    display: inline-flex;
}

.main-menu > div {
  margin: 5px;
  cursor: pointer;
}

.home,.about,.contact{
    height:800px;
}

.home{
  background-color: rgb(221, 148, 148);
  
}

.about{
  background-color: rgb(172, 206, 145);
}

Step 2: Creating references

Now that we have done creating the skeleton of the app, it is time to add refs. Before, the React hooks are introduced refs are created by calling React.createRef(). However, now, you can use react hook useRef() to create ref objects.

Add the following code to App.js. Note that you need to import useRef hook from ‘react’.

import React, { useRef } from 'react'
import './App.css';


function App() {
    const homeOnClickRef = useRef(null);
    const aboutOnClickRef = useRef(null);
    const contactOnClickRef = useRef(null);
    
    return (
    <div>
        <ul className='main-menu'>
          <div>HOME</div>
          <div>ABOUT</div>
          <div>CONTACT</div>
        </ul>
        <Home/>
        <About/>
        <Contact/>      
    </div>
  )

Ref object has a property named current. We are going to use this property to use the scrollIntoView() method of this property.

You can learn about scrollIntoView() method here

Now, we need to create a function called scrollEffect(). It takes ref object as a parameter.

const scrollEffect = ( targetRef ) =>{
  targetRef.current.scrollIntoView({
    behavior: 'smooth',
    block: 'start',
  });
}

Step 3: Adding events

We are going to initiate the scroll effect when we click on the menu items in the header. So we need trigger scrollEffect() function on onClick event.

<ul className='main-menu'>
          <div onClick = { () =>scrollEffect(homeOnClickRef) }>HOME</div>
          <div  onClick = { ()=>scrollEffect(aboutOnClickRef) }>ABOUT</div>
          <div onClick = { () =>scrollEffect(contactOnClickRef) }>CONTACT</div>
 </ul>

Step 4: Passing ref object with ref attribute

ref is an attribute you need to use to passe ref objects to other components. So, add the ref attribute to components called in the App.js and assigned your custom ref objects as below.

...........
<Home ref = { homeOnClickRef }/>
<About ref = { aboutOnClickRef }/>
<Contact ref = { contactOnClickRef } />
...........

Step 5. Modify Components

Now, we need to change to code of the components. I will show you how to do to the Contact component.

First, we need to add a second argument(myref) to reference the ref object passing from the App.js.

const Contact =({},myref) => (
    <div ref={  myref }className="contact"></div>
)

Or

const Contact =(props,myref) => (
    <div ref={  myref }className="contact"></div>
)

Then you need to wrap the component in React.forwardRef(), which is necessary when you pass ref to child components.

const Contact = React.forwardRef(({},myref) => (
    <div ref={  myref }className="contact"></div>
))

Now, you can do the same for the other two components.

A little challenge…

As you can on the video below, there is a button to go back to the header section. Your challenge is to make that button. It is up to you to add any content you want for each component. Hope you enjoy it.

Related Post

Leave a Reply

Your email address will not be published. Required fields are marked *