5

I am experiencing some issues with next/link when I use it in my app.

I have a reusable component that renders a button. This component is used twice on the page with different urls each time.

When the page is in desktop view, the button works perfectly. I can navigate from one page to another. When I reduce the size of the screen to either tablet or mobile one redirects correctly and the other one does not respond as expected.

To work around the issue I have enclosed the area inside a link so the user can click outside the button area and still be directed to the page but it is not really the experience I want to offer to the user.

I never had this before. Can someone tell me how to fix this or why is it behaving this way, please? thanks.

const Banner = ({
  purpose,
  imageUrl,
  title1,
  title2,
  desc1,
  linkName,
  buttonText,
}) => {
  return (
    <div className="row flex-lg-row-reverse align-items-center g-5  justify-content-center">
      <div className=" col-10 col-sm-8 col-lg-6">
        <Image
          className="d-block img-fluid mx-lg-auto"
          src={imageUrl}
          width={700}
          height={500}
          alt="banner"
          loader={myLoader}
        />
      </div>
      <Link href={linkName} passHref>
        <div className="col-lg-4 p-3 text-center text-lg-start border-0">
          <h1 className="display-6 fw-bold lh-1 mb-3">{purpose}</h1>
          <p className="lead">
            {title1}
            <br /> {title2}
          </p>
          <p className="lead">{desc1}</p>

          <button className="btn link btn-primary btn-xl w-100">
            <Link href={linkName} passHref>
              <a> {buttonText}</a>
            </Link>
          </button>
        </div>
      </Link>
    </div>
  );
};

export default function Home({ data }) {
  const {
    results: {
      client: { secondhandListing },
    },
  } = data;
  //console.log('index page results',secondhandListing);

  return (
    <>
      <div
        data-spy="scroll"
        data-bs-target="main-nav"
        data-offset="0"
        className="scrollspy-example"
        tabIndex="0"
      >
        <Services />
        <div className="section d-flex justify-content-center my-5">
          <h1 className="my-5" id="#scrollspyHeading2">
            Properties
          </h1>
        </div>
        <div className="container-fluid d-flex  justify-content-xxl-between align-items-center flex-wrap flex-lg-nowrap">
          <div className="section d-flex">
            <Banner
              purpose="Rent a Home"
              title1="Rental Homes for"
              title2="Everyone"
              desc1="Explore Apartments, Villas, Homes"
              desc2="and more"
              buttonText="Explore Renting"
              linkName="/search?operationType=rent"
              imageUrl="https://bayut-production.s3.eu-central-1.amazonaws.com/image/145426814/33973352624c48628e41f2ec460faba4"
            />
          </div>
          <div className="section d-flex">
            <Banner
              purpose="Buy a Home"
              title1="Find, Buy & Own"
              title2="Your Dream Home"
              desc1="Explore Apartments, Villas, Homes"
              desc2="and more"
              buttonText="Explore Buying"
              linkName="/search?operationType=sale"
              imageUrl="https://bayut-production.s3.eu-central-1.amazonaws.com/image/145426814/33973352624c48628e41f2ec460faba4"
            />
          </div>
        </div>
        <Team />
        <Contact />
      </div>
    </>
  );
}
RubenSmn
  • 4,091
  • 2
  • 5
  • 24
Leo
  • 481
  • 2
  • 9
  • 20

3 Answers3

5

Run the new-link codemod to automatically upgrade previous versions of Next.js to the new <Link> usage:

npx @next/codemod new-link .

This will change <Link><a id="link">Home<a></Link> to <Link id="link">Home</Link>.

Alternatively, you can add the legacyBehavior prop <Link legacyBehavior><a id="link">Home<a></Link>.

Raja P.B.
  • 151
  • 2
  • 4
2

<button> and <a> do not allow interactive content to be their content.

That said, you're passing invalid children to your <Link> component and to the <button> element:

  <Link href={linkName} passHref>
    <div className="col-lg-4 p-3 text-center text-lg-start border-0">
      <h1 className="display-6 fw-bold lh-1 mb-3">{purpose}</h1>
      <p className="lead">{title1}<br /> {title2}</p>
      <p className="lead">{desc1}</p>
      
      {/* Invalid child */}
      <button className="btn link btn-primary btn-xl w-100">
        {/* Invalid child */}
        <Link href={linkName} passHref>
         <a> {buttonText}</a>
        </Link>
      </button>
    </div>
  </Link>

That may be the reason of why your component is behaving oddly.

PS. Formatting your code helps by making it more readable. :). You can do that by setting ESLint and Prettier up.

pmartiner
  • 21
  • 5
1

You maybe need to add the legacyBehavior as props in the next/link component.

import Link from 'next/link'

function Legacy() {
  return (
    <Link href="/about" legacyBehavior>
      <a>About Us</a>
    </Link>
  )
}

export default Legacy

docs: https://nextjs.org/docs/api-reference/next/link#if-the-child-is-a-tag