vercel / next.js

The React Framework
https://nextjs.org
MIT License
124.67k stars 26.61k forks source link

next/link prefixing urls with / only on client side #19922

Open ciruz opened 3 years ago

ciruz commented 3 years ago

Bug report

Describe the bug

With the latest next.js version (10.0.3), I noticed a new warning in my console, without changing anything at the code. When using next/link a slash / get's prefixed to the url on client side but not on server. I had no errors on 10.0.1.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Clone any next.js example repo (for ex.: using-router-app)
  2. Modify your index.js page to this:
    
    import Link from "next/link";

export default function Home() { return (

test

); }

3. Check the console

react-dom.development.js:88 Warning: Prop href did not match. Server: "test" Client: "/test" in a (at pages/index.js:7) in Link (at pages/index.js:6) in div (at pages/index.js:5) in Home (created by App) in App in ErrorBoundary (created by ReactDevOverlay) in ReactDevOverlay (created by Container) in Container (created by AppContainer) in AppContainer in Root



## Expected behavior

Prefix the url on client and server side, or don't prefix it at all.

## Screenshots

![image](https://user-images.githubusercontent.com/987947/101328645-90194580-3870-11eb-835b-e376d93007c0.png)

## System information

- OS: Windows 10
- Browser Chrome
- Version of Next.js: v10.0.3
- Version of Node.js: v14.15.1
- Deployment: yarn dev
sarangkartikey50 commented 3 years ago

Fix proposal

Currently I have tried by making removing the trailing slash in the client side. Now at both Server and Client the href will be 'about' and 'about' respectively. Not sure whether correct or not. pull request

next-server/lib/router/router.ts

const resolvedHref =
      finalUrl.origin === base.origin
-        ? finalUrl.href.slice(finalUrl.origin.length)
+        ? finalUrl.href.slice(finalUrl.origin.length + 1)
        : finalUrl.href
qw-in commented 3 years ago

I opened #22165 however it seems likely to be a duplicate so I will close. Gist is below:

// This
<Link href={{ href: "/about" }}>
  <a>About</a>
</Link>
// Causes `Warning: Prop `href` did not match. Server: "" Client: "/"`

Sandbox: https://codesandbox.io/s/nextjs-client-server-mismatch-75lkl?file=/pages/index.js

hpachy commented 3 years ago

same problem...

Warning: Prop href did not match. Server: "" Client: "/xxx/[xxx]"

akellbl4 commented 3 years ago

@qw-in as far as I know If you want to pass href as url object you should pass it like that:

<Link href={{ pathname: "/about" }}>
  <a>About</a>
</Link>

@hpachy could you share the piece of code that cause that warning.

hpachy commented 3 years ago

My problem was because I add one more '/' like the following :


<Link href={{ pathname: "/about/" }}>
  <a>About</a>
</Link>

do not reproduce it aha! (so was totaly my bad)

qw-in commented 3 years ago

@qw-in as far as I know If you want to pass href as url object you should pass it like that

href is in both the docs & the typescript definitions if I'm remembering correctly

akellbl4 commented 3 years ago

Docs don't describe possible fields for URL Object. You can get info only from examples. You are right, typescript has href but I think next/router just doesn't work with this field.

It's two possible ways to solve that support whole URL Object or fix typings :)

akellbl4 commented 3 years ago

I've tried to go deeper into the problem. @qw-in as I told Next.js don't handle href inside Url Object. You can check out what params is handled here: https://github.com/vercel/next.js/blob/f06c58911515d980e25c33874c5f18ade5ac99df/packages/next/next-server/lib/router/utils/format-url.ts#L29

Also, as I can see the solution that was proposed by @sarangkartikey50 works not really well because it removes the first slash from any passed href. It removes warning but the result is unexpected.

Page code:

export default function Home() {
  return (
    <ul>
      <li>
        <Link href="about">
          <a>a</a>
        </Link>
      </li>
      <li>
        <Link href="/about">
          <a>a</a>
        </Link>
      </li>
    </ul>
  );
}

Resoult HTML:

<ul>
  <li>
    <a href="about">a</a>
  </li>
  <li>
    <a href="about">a</a>
  </li>
</ul>

The real problem in function isLocalURL. It's not able to work on the server and check if href is local. Maybe better solutions could be around that.

marnixhoh commented 3 years ago

I am experiencing a similar issue after adding i18n / Internationalized Routing to my next.config.js file. Note, that without adding that, this error does not occur. The i18n section of my next.config.js file:

i18n: {
    locales: ['en-US', 'nl'],
    defaultLocale: 'en-US',

    domains: [{
        domain: 'localhost',
        defaultLocale: 'nl',
        locales: ['en-US']
    }]
},

Below is the error I receive. Note that I am developing on http://localhost, but for some reason next.js is forcing https on the server:

Warning: Prop `href` did not match. Server: "https://localhost/" Client: "/"

Next version: 10.0.8

erwanriou commented 3 years ago

+1 here, i am using the i18n through multiple domains for internationalisation and my locale domains are returning this error. Also all my link that were previously just going to /fr or /es depending of language switch are now enforcing the reditect to the attributed default language of each domain.

luk3skyw4lker commented 2 years ago

Is this still a problem? I could take a look if it still is.

Babbili commented 2 years ago

i had the same issue, and i solve it by adding a "/" to the href on the client, this is the way,

export default function Home() {
  return (
        <Link href={`/${yourPath}`} >
          <a>a</a>
        </Link>
  )
}
itsmingjie commented 2 years ago

Hi! I'm one of the program coordinators of a nonprofit program called CodeDay Init, and we partner with colleges to help CS students make their first open-source contribution.

We'll claim this issue for now and a group of students will be on it soon with mentorship! If this issue is no longer relevant, please let me know.