0

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.

Mihai INT
  • 15
  • 1
  • 4

4 Answers4

0

Two points here:

  1. As per the nextjs, passHref has to be used if a custom element is used as a child of Link tag instead of an anchor tag.
  2. As per the same docs value of href should be '/#enews' not '#enews'
Akhil
  • 1
  • 1
0

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>
Sean W
  • 5,663
  • 18
  • 31
0

In order to scroll to a specific section, both linking component and section should be in the same component (or inner component). Otherwise use the full page url followed by the id.

Example: Link href='/pagename/#id'>Navigate

midhun
  • 1
  • 2
0

With the latest version of NextJS and their component, you need to set the scroll prop to false. This is because the behavior by default will try to scroll to the top of the page after a navigation.

Example usage:

<Link
  href="#sign-up"
  className="text-xl font-medium text-blue-600 hover:text-blue-800"
  scroll={false}
>
  Archor Text
</Link>

Also, using <a> tags within the <Link> component is deprecated now.

I wrote a little more in depth about it when using smooth scroll with Tailwind and NextJS here.