![](/img/trans.png)
[英]Next.js - On Shallow routing for dynamic path it is removing the basePath from browser url
[英]Next.js - Shallow routing with dynamic routes
當嘗試在 Next.js 中使用動態路由進行淺層路由時,頁面會刷新並被淺層忽略。 似乎很多人對此感到困惑。
假設我們從下一頁開始
router.push(
'/post/[...slug]',
'/post/2020/01/01/hello-world',
{ shallow: true }
);
然后我們轉到另一篇博文:
router.push(
'/post/[...slug]',
'/post/2020/01/01/foo-bar',
{ shallow: true }
);
這樣不會觸發淺層路由,瀏覽器刷新,為什么呢?
在代碼庫中,很明顯這是一個功能:
// If asked to change the current URL we should reload the current page
// (not location.reload() but reload getInitialProps and other Next.js stuffs)
// We also need to set the method = replaceState always
// as this should not go into the history (That's how browsers work)
// We should compare the new asPath to the current asPath, not the url
if (!this.urlIsNew(as)) {
method = 'replaceState'
}
我可以使用window.history.pushState()
手動實現同樣的效果,盡管這當然不是一個好主意:
window.history.pushState({
as: '/post/2020/01/01/foo-bar',
url: '/post/[...slug]',
options: { shallow: true }
}, '', '/post/2020/01/01/foo-bar');
由於 Next.JS 的內部 API 隨時可能發生變化......我可能會遺漏一些東西......但為什么在這種情況下會忽略 shallow ? 似乎很奇怪。
我認為這是預期的行為,因為您正在路由到新頁面。 如果您只是更改查詢參數,淺路由應該可以工作,例如:
router.push('/?counter=10', undefined, { shallow: true })
但是您正在使用路由參數
router.push(
'/post/[...slug]',
'/post/2020/01/01/hello-world',
{ shallow: true }
);
這表明您正在路由到一個新頁面,它會卸載當前頁面,加載新頁面,並等待數據獲取,即使我們要求進行淺層路由,這在文檔中提到過淺路由警告。
順便說一句,您說“頁面已刷新”,但即使在沒有使用shallow: true
的情況下, router.push
也不會刷新頁面。 畢竟這是一個單頁應用程序。 它只是呈現新頁面並運行getStaticProps
、 getServerSideProps
或getInitialProps
。
淺路由使您能夠更新路徑名或查詢參數而不會丟失 state 即,僅更改路由的 state。但條件是,您必須在同一頁面上(如文檔警告圖像中所示) 。
為此,您必須將第二個參數傳遞給未定義的 router.push 或 Router.push。 否則,卸載第一頁后將加載新頁面,您將無法獲得預期的行為。
我的意思是淺層路由將不再適用於路徑名更改,這是因為我們選擇加載新頁面,而不僅僅是 url。 希望這可以幫助
例子
import { useEffect } from 'react'
import { useRouter } from 'next/router'
// Current URL is '/'
function Page() {
const router = useRouter()
useEffect(() => {
// Always do navigations after the first render
router.push('/post/[...slug]', undefined, { shallow: true })
}, [])
useEffect(() => {
// The pathname changed!
}, [router.pathname ])
}
export default Page
實際上,根據文檔描述,我相信您錯誤地使用了此push
function。 請參閱來自docs的以下代碼:
import Router from 'next/router'
Router.push(url, as, options)
文檔說:
url
- 要導航到的 URL。 這通常是頁面的名稱as
- 將在瀏覽器中顯示的 URL 的可選裝飾器。 默認為url
options
- 可選 object,具有以下配置選項: shallow:更新當前頁面的路徑,無需重新運行 getStaticProps、getServerSideProps 或 getInitialProps。 默認為假
這意味着您應該將確切的 URL 作為第一個參數傳遞,如果您想將其顯示為裝飾名稱,則傳遞第二個參數,第三個只需傳遞選項,因此您應該編寫如下:
router.push(
'/post/2020/01/01/hello-world',
undefined,
undefined
);
對於淺層路由,您應該使用確切的示例:
router.push('/?counter=10', undefined, { shallow: true });
事實上,用你的代碼,你創建了一個新的路由,刷新是不可避免的。
如果避免在嵌套路由中重新呈現是您的問題,那么解決方案可能是將您的頁面嵌套在布局組件中,如下所述:
https://nextjs.org/docs/basic-features/layouts
https://adamwathan.me/2019/10/17/persistent-layout-patterns-in-nextjs/
好的,所以這個答案基於我的第一個答案(和問題澄清):
#1問題是: This does not trigger shallow routing, the browser refreshes, why?
=>查看我的最后一個答案,了解next.js
如何處理文件結構。
#2如果你想處理無限的 URL 參數:
您將必須遵循以下文件結構:
.
├── pages
│ ├── post
│ │ └──[...slug].js // or [...slug]/index.js
│ ├── about.js
│ └── index.js
├── public
│ └── ...
├── .gitignore
├── package.json
├── package-lock.json
└── README.md
[...蛞蝓].js:
export default function Post({ post }) {
return (
<div>
<h1>Post is here{}</h1>
{JSON.stringify(post)}
</div>
);
}
export async function getStaticPaths() {
return {
paths: [
{ params: { slug: ["*"] } },
],
fallback: true
};
}
export async function getStaticProps(context) {
console.log("SLUG: ", context);
const { params = [] } = context || {};
const res = await fetch(`https://api.icndb.com/jokes/${params && params.slug[0] || 3}`);
const post = await res.json()
return { props: { post } }
}
./index.js:
import Link from 'next/link';
import Router from 'next/router'
export default function Home() {
const handleClick = e => {
e.preventDefault();
Router.push(
'/post/[...slug]',
'/post/2/2/4',
{ shallow: true }
);
}
return (
<div className="container">
<div>
<Link href="/about">
<a>About</a>
</Link>
</div>
<hr />
<div>
<Link
href={`/post/[...slug]?slug=${2}`}
as={`/post/${2}`}
>
<a>
<span>
Post:
</span>
</a>
</Link>
<hr />
<div>
<button onClick={handleClick}>
Push me
</button>
</div>
</div>
</div>
)
}
任何深/post/any/url/long/will_return_slugfile
再次!!! 在next.js
中,您必須注意路由中的文件系統結構。 (正如我在上一個回答中提到的)
pages/post/[[...slug]].js will match /post, /post/a, /post/a/b, and so on.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.