Search code examples
next.jshrefnext-link

My Link with href doesn't scroll even though the link changes. Nextjs


I'm working on a react with nextjs project. I'm using Link to scroll to a specific section on the same page.

Here is one of the components that use Link:

import styles from './section1.module.scss';
import Image from 'next/image';
import Button from '@material-ui/core/Button';
import tought_process from '../../../public/thought_process.png';
import Link from 'next/link';

const Section1 = () => {
  return (
    <div className={styles.container}>
      <div className={styles.left}>
        <div className={styles.leftContainer}>

          <Link href='#enews'>
            <div className={styles.buttonContainer}>
              <Button className={styles.buttonstyle1}>Get started</Button>
            </div>
          </Link>
        </div>
      </div>
      <div className={styles.right}>
        <Image
          src={tought_process}
          className={styles.imageStyle}
          alt='how to think about organizing'
          layout='responsive'
          priority
        />
      </div>
    </div>
  );
};

export default Section1;

And here i mark the element with the id:

      <div {...handlers} className={styles.bigBody}>
        <NavBar open={menuOpen} toggle={setMenuOpen} scrollY={scrollY} />

        <SideMenu open={menuOpen} toggle={setMenuOpen} scrollY={scrollY} />

        <div className={styles.sections}>
          <Section1 />
          <Section2 />
          <Section3 id='enews' />
          <Section4 />
        </div>

Can't figure out what i'm doing wrong.


Solution

  • Multiple clickable elements are wrapping each other. Remove the button and add the anchor element.

    <Link href="#enews">
     <a>Get started</a>
    </Link>
    
    <Link href="#enews">
     <a className={styles.buttonContainer}>
      <span className={styles.buttonstyle1}>Get started</span>
     </a>
    </Link>
    

    I'd recommend updating the styles so you can remove the inner span element.


    I use a custom link component that does a few things (not shown); one is smooth scroll to hash routes if the browser supports smooth scrolling (not Safari).

    import NextLink, { LinkProps } from "next/link";
    import { HTMLProps, MouseEvent, FC } from "react";
    
    export const Link: FC<LinkProps & HTMLProps<HTMLAnchorElement>> = ({ as, children, href, replace, scroll, shallow, passHref, ...rest}) => {
      const onClick = (event: MouseEvent<HTMLAnchorElement>) => {
        if (href.startsWith("#")) {
          event.preventDefault();
          const destination = document.getElementById(href.substring(1));
          if (destination) destination.scrollIntoView({ behavior: "smooth" });
        }
      };
      return (
        <NextLink as={as} href={href} passHref={passHref} replace={replace} scroll={scroll} shallow={shallow}>
          <a href={href} {...rest} onClick={onClick}>
            {children}
          </a>
        </NextLink>
      );
    };
    

    I removed new lines to condense the code block

    If you went with the above approach, don't include the anchor tag since it's automatically included.

    import { Link } from "./custom/path/link"
    
    <Link href="#enews">Get started</Link>