skip to Main Content

Suppose I have my "/" page and another page "/Blog". I want to go from /Blog to /#Blogs, which is a route containing the specific element ID. I am trying to do this using the Link component.

here is the code snippet for my Link component:

<Link
href={displayAll ? "/#Blogs" : "/Blog"}
scroll={false}
{displayAll ? "Back Home" : "Read more"}
</Link>

P.s, I successfully navigate to localhost:3000/#Blogs, but I am redirected to the top of the page, rather than the element with id="Blogs"

2

Answers


  1. you can simply use:

    href={ "/Blogs"+ "#ID"}
    

    but be careful, its a little more complicated than that. when you navigate between pages, NextJS default behaviour is consider it server component, and if you wrap your page in Suspend component with a fallback, this wont work.
    in that case, you have to do it manually, i.e when page loaded, push it to your desired element with UseEffect hook.

    Login or Signup to reply.
  2. The issue arises because Next.js’s Link component doesn’t automatically handle scrolling to an element with a specific ID when navigating between pages. While you’re successfully navigating to /#Blogs, Next.js doesn’t scroll to the element with id="Blogs" because it only works on the same page by default.

    To fix this issue, you need to manually handle the scrolling. You can achieve this by listening to the router events and using JavaScript to scroll to the desired element. Here’s how you can do it:

    Updated Code Snippet

    import { useRouter } from 'next/router';
    import { useEffect } from 'react';
    import Link from 'next/link';
    
    const MyComponent = ({ displayAll }) => {
      const router = useRouter();
    
      useEffect(() => {
        const handleRouteChange = (url) => {
          if (url.includes('#')) {
            const [, hash] = url.split('#');
            const element = document.getElementById(hash);
            if (element) {
              element.scrollIntoView({ behavior: 'smooth' });
            }
          }
        };
    
        router.events.on('routeChangeComplete', handleRouteChange);
        return () => {
          router.events.off('routeChangeComplete', handleRouteChange);
        };
      }, [router.events]);
    
      return (
        <Link href={displayAll ? '/#Blogs' : '/Blog'} scroll={false}>
          {displayAll ? 'Back Home' : 'Read more'}
        </Link>
      );
    };
    
    export default MyComponent;
    

    Explanation:

    1. useEffect and router.events:

      • Listen for routeChangeComplete events to detect when navigation finishes.
      • If the URL includes a hash (e.g., #Blogs), extract the ID and find the corresponding DOM element.
    2. scrollIntoView:

      • Smoothly scrolls to the element with id="Blogs".
    3. scroll={false}:

      • Prevents the default scrolling behavior of the Link component, allowing custom behavior instead.

    Notes:

    • This approach ensures compatibility with Next.js routing and works for navigation both between pages and within the same page.
    • Add an id="Blogs" to your target element in the / page for this to work.

    Let me know if you encounter any issues!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search