Using scrollIntoView() with React components
Oscar Wilde said, “Imitation is the sincerest form of flattery that mediocrity can pay to greatness.” I think I’d prefer the term junior developer over mediocre but nonetheless, I am currently developing my personal portfolio website and I have found inspiration from where else, but other portfolio websites. One feature that I’ve repeatedly found are buttons on landing pages that when clicked, simply scroll down to the rest of the content. I was determined to add that feature to my website. Here’s how I did it with functional React components and the useRef hook.
I started off with an App component rendering two other components, Landing and About.
//App...import React from 'react';
import Landing from './landing/Landing';
import About from './about/About';const App = () => {
return(
<div>
<Landing />
<About />
</div>
);
};
export default App;//Landing...const Landing = () => {
return(
<div>
Hello, I'm Karl Benbeneck.
<button>
View my work
</button>
</div>
);
};//About...const About = () => {
return(
<section>
<h2>About Me</h2>
//who I am, who I was, how I got here, my work etc...
</section>
);
};
The problem: How can a user click the button being rendered in the Landing component and somehow scroll to the About component?
The solution: The useRef hook paired with the Element.scrollIntoView() method.
The scrollIntoView() method can be called on DOM elements. With vanilla JavaScript, this problem could be solved by adding an Id to the About component element and calling the scroll method on click. React requires a slightly different approach.
<button onclick="document.getElementById('about').scrollIntoView()">
Setting up useRef
To access virtual DOM elements in React, the useRef hook is needed. So let’s get importing.
//App...import React, { useRef ) from 'react';
Inside the App component, above the return statement, we create a prop to be passed to the About component.
//App...
const aboutRef = useRef()
...
<About refProps={aboutRef} />
<Landing />
Inside the About component, we destructure out the passed in refProps and set the section node as the ref object.
//About...
const About = ({ refProps }) => {
return(
<section ref={refProps}>
useRef will now return the section element from the About component in its .current property.
Now let’s add the scroll behavior
Inside the App component, we create a scrollCallback function to be passed to the Landing component. The scrollIntoView() method can accept several optional arguments. We will include an object to set the animation to smooth.
//App...
const aboutRef = useRef()
const scrollCallback = () => {
aboutRef.current.scrollIntoView({ behavior: 'smooth' })
}
...<About refProps={aboutRef} />
<Landing scrollCallback={scrollCallback} />
Inside the Landing component, we accept the callback function as props and call it when the button is clicked.
//Landing...
const Landing = ({ scrollCallback }) => {
...
<button onClick={() => scrollCallback()}>
Problem solved.
There is still much to add to my portfolio website such as project demo videos, accessibility considerations, as well as basic responsiveness. I am currently looking for opportunities in the Tampa Bay, Florida area but I am open to remote opportunities anywhere. Please find me on LinkedIn or Github.