'How to navigate to another page with a smooth scroll on a specific id with react router and react scroll
i am trying to make navBar that navigate to another page and scroll down to some id on this page
this is the navBar component for my protofolio whih have 3 links the Projects should go to Home and then scroll down to projects id in the Project section
import React, { Component } from "react";
import logo from "../../images/logo.png";
import { Link } from "react-router-dom";
import Scroll from "react-scroll";
import "./NavBar.css";
const ScrollLink = Scroll.Link;
class NavBar extends Component {
render() {
return (
<div className="NavBar">
<Link to="/" className="logo-container">
<img className="logo" src={logo} alt="Mahboub logo"></img>
</Link>
<div className="Nav-links">
<Link to="/">Home</Link>
<ScrollLink
className="navy"
smooth={true}
duration={500}
to="projects"
>
projects
</ScrollLink>
<Link to="/">Contacts</Link>
</div>
</div>
);
}
}
export default NavBar;
here is the prjects component for project section in home page
function Projects() {
return (
<div className="Home-Projects">
<Element id="projects">
<h1>Projects</h1>
</Element>
<div className="Projects-container">
<ProjectElement />
</div>
</div>
);
}
Solution 1:[1]
If "duration" parameter isn't of great importance for you and you have no problems with Hooks, I'd like to suggest solution as follows.
You get rid of Scroll component and use plain Link from RR in your NavBar like so
<Link to="/#projects">projects</Link>Since RR v5.1 Hooks was introduced. There is useLocation hook among them. Insert that hook at the very beginning of your Projects component like so:
function Projects() { const location = useLocation() ...
When you hit Link from p.1, you get new location object of the form
location = {
...
pathname:"/",
...
hash: "#projects"
}
- Call
useEffecthook afteruseLocationlike so:
useEffect(()=> {
if (location.hash) {
let elem = document.getElementById(location.hash.slice(1))
if (elem) {
elem.scrollIntoView({behavior: "smooth"})
}
} else {
window.scrollTo({top:0,left:0, behavior: "smooth"})
}
}, [location,])
And thats it. As you can see, if there is no hash in your url, your page would scroll to the top. Use [locaton,] as useEffect dependency prevents form scrolling when your page component rerenders not because of location changes.
Solution 2:[2]
I just add this in the index.css
html {
scroll-behavior: smooth;
}
and this
<ScrollLink
className="navy"
smooth={true}
duration={500}
to="projects"
>
projects
</ScrollLink>
became
<a href="/#projects">Projects</a>
this was so fast and simple and worked prefectly
Solution 3:[3]
For next.js
//https://yourdomain.com/page?scroll=scroll_here <---
import { useEffect } from 'react';
import { Flex } from '@chakra-ui/react';
import { useRouter } from 'next/router';
export default function DecisionAreaFlex(props) {
const router = useRouter();
useEffect(() => {
console.log('router query', router.query.scroll);
if (router.query.scroll) {
let elem = document.getElementById(router.query.scroll);
if (elem) {
elem.scrollIntoView({ behavior: 'smooth' });
}
} else {
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
}
}, [router]);
return (
<Flex
alignSelf="center"
justifyContent="center"
alignItems="center"
mt="15px"
id={'scroll_here'} // <---
>
{props.children}
</Flex>
);
}
Solution 4:[4]
I've created a query param called anchor, and with that I can control the scroll based on the useEffect.
The link: /about?anchor=capabilities
The code on the page which should have the smooth scroll:
const router = useRouter();
useEffect(()=> {
if (router?.query?.anchor) {
let elem = document.getElementById(router?.query?.anchor)
if (elem) {
elem.scrollIntoView({behavior: "smooth"});
}
}
}, [router?.query?.anchor])
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | DmitriyBelovol |
| Solution 2 | Ahmed Mahboub |
| Solution 3 | Gökhan Geyik |
| Solution 4 | tdy |
