useRouter
若您想在應用程式的任何函式元件中存取 router
物件,可以使用 useRouter
鉤子,請參考以下範例:
useRouter
是一個 React 鉤子 (React Hook),意味著它無法與類別元件一起使用。您可以選擇使用 withRouter 或將您的類別元件包裹在函式元件中。
router
物件
以下是 useRouter
和 withRouter
返回的 router
物件定義:
pathname
:String
- 當前路由檔案的路徑(位於/pages
之後)。因此不包含basePath
、locale
和結尾斜線 (trailingSlash: true
)。query
:Object
- 解析為物件的查詢字串,包含動態路由參數。如果頁面未使用伺服器端渲染 (Server-side Rendering),在預渲染時會是空物件。預設為{}
asPath
:String
- 瀏覽器中顯示的路徑,包含搜尋參數並遵循trailingSlash
配置。不包含basePath
和locale
。isFallback
:boolean
- 當前頁面是否處於後備模式 (fallback mode)。basePath
:String
- 當前的 basePath(若啟用)。locale
:String
- 當前的語言環境 (locale)(若啟用)。locales
:String[]
- 所有支援的語言環境(若啟用)。defaultLocale
:String
- 當前的預設語言環境(若啟用)。domainLocales
:Array<{domain, defaultLocale, locales}>
- 任何已配置的網域語言環境。isReady
:boolean
- 路由器欄位是否已在客戶端更新並準備就緒。應僅在useEffect
方法中使用,不用於伺服器端的條件渲染。相關使用案例請參閱自動靜態優化頁面 (automatically statically optimized pages) 的文件。isPreview
:boolean
- 應用程式當前是否處於預覽模式 (preview mode)。
如果頁面使用伺服器端渲染或自動靜態優化 (automatic static optimization),使用
asPath
欄位可能導致客戶端與伺服器不一致。在isReady
欄位為true
之前,請避免使用asPath
。
以下方法包含在 router
中:
router.push
處理客戶端導航,此方法適用於 next/link
不足的情況。
url
:UrlObject | String
- 要導航至的 URL(UrlObject
屬性請參閱 Node.JS URL 模組文件)。as
:UrlObject | String
- 瀏覽器 URL 欄位中顯示路徑的選用裝飾器。在 Next.js 9.5.3 之前,這用於動態路由。options
- 包含以下配置選項的選用物件:scroll
- 選用布林值,控制導航後是否滾動至頁面頂部。預設為true
shallow
: 更新當前頁面的路徑而不重新執行getStaticProps
、getServerSideProps
或getInitialProps
。預設為false
locale
- 選用字串,表示新頁面的語言環境
外部 URL 不需要使用
router.push
。window.location 更適合此類情況。
導航至預定義路由 pages/about.js
:
導航至動態路由 pages/post/[pid].js
:
將使用者重定向至 pages/login.js
,適用於身份驗證 (authentication) 後的頁面:
導航後重置狀態
在 Next.js 中導航至相同頁面時,頁面狀態不會預設重置,因為除非父元件變更,否則 React 不會卸載元件。
在上面的範例中,在 /one
和 /two
之間導航不會重置計數。useState
在渲染之間保持不變,因為頂層 React 元件 Page
是相同的。
如果您不希望此行為,有幾個選項:
-
使用
useEffect
手動確保每個狀態更新。在上面的範例中,可以這樣做: -
使用 React
key
來告訴 React 重新掛載元件。若要對所有頁面執行此操作,可以使用自訂應用程式:pages/_app.js
使用 URL 物件
您可以像在 next/link
中一樣使用 URL 物件。適用於 url
和 as
參數:
router.replace
類似於 next/link
中的 replace
屬性,router.replace
會防止在 history
堆疊中添加新的 URL 條目。
router.replace
的 API 與router.push
完全相同。
請看以下範例:
router.prefetch
預取頁面以實現更快的客戶端導航。此方法僅適用於沒有使用 next/link
的導航,因為 next/link
會自動處理頁面預取。
這是一個僅在生產環境中有效的功能。Next.js 在開發環境中不會預取頁面。
url
- 要預取的 URL,包括明確路由(例如/dashboard
)和動態路由(例如/product/[id]
)as
-url
的選用裝飾器。在 Next.js 9.5.3 之前,這用於預取動態路由。options
- 包含以下允許欄位的選用物件:locale
- 允許提供與當前語言環境不同的語言環境。如果為false
,url
必須包含語言環境,因為不會使用當前語言環境。
假設您有一個登入頁面,登入後將使用者重定向至儀表板。對於這種情況,我們可以預取儀表板以實現更快的轉換,如下例所示:
router.beforePopState
在某些情況下(例如使用自訂伺服器 (Custom Server)),您可能希望監聽 popstate 並在路由器處理之前執行某些操作。
cb
- 在傳入popstate
事件時執行的函式。該函式接收事件狀態作為包含以下屬性的物件:url
:String
- 新狀態的路由。這通常是page
的名稱as
:String
- 將在瀏覽器中顯示的 URLoptions
:Object
- router.push 發送的附加選項
如果 cb
返回 false
,Next.js 路由器將不會處理 popstate
,您需要自行處理。請參閱停用檔案系統路由 (Disabling file-system routing)。
您可以使用 beforePopState
來操作請求或強制 SSR 刷新,如下例所示:
router.back
在歷史記錄中返回。等同於點擊瀏覽器的返回按鈕。它執行 window.history.back()
。
router.reload
重新載入當前 URL。等同於點擊瀏覽器的刷新按鈕。它執行 window.location.reload()
。
router.events
您可以監聽 Next.js 路由器內發生的不同事件。以下是支援的事件列表:
routeChangeStart(url, { shallow })
- 當路由開始變更時觸發routeChangeComplete(url, { shallow })
- 當路由完全變更後觸發routeChangeError(err, url, { shallow })
- 當變更路由時發生錯誤或路由載入被取消時觸發err.cancelled
- 表示導航是否被取消
beforeHistoryChange(url, { shallow })
- 在變更瀏覽器歷史記錄之前觸發hashChangeStart(url, { shallow })
- 當 hash 將變更但頁面不變時觸發hashChangeComplete(url, { shallow })
- 當 hash 已變更但頁面不變時觸發
須知:此處的
url
是瀏覽器中顯示的 URL,包含basePath
。
例如,要監聽路由器事件 routeChangeStart
,請開啟或建立 pages/_app.js
並訂閱該事件,如下所示:
我們在此範例中使用自訂應用程式 (Custom App) (
pages/_app.js
) 來訂閱事件,因為它在頁面導航時不會卸載,但您可以在應用程式的任何元件中訂閱路由器事件。
路由器事件應在元件掛載時註冊(useEffect 或 componentDidMount / componentWillUnmount),或在事件發生時強制註冊。
如果路由載入被取消(例如快速連續點擊兩個連結),routeChangeError
會觸發。傳遞的 err
將包含設為 true
的 cancelled
屬性,如下例所示:
潛在的 ESLint 錯誤
router
物件上的某些方法會返回一個 Promise。如果您啟用了 ESLint 規則 no-floating-promises,可以考慮全局禁用該規則,或僅在受影響的代碼行禁用。
如果您的應用程式需要此規則,您應該對 Promise 使用 void
操作符,或者使用 async
函數、await
Promise,然後對函數調用使用 void。當方法在 onClick
處理程序內部調用時,此方法不適用。
受影響的方法包括:
router.push
router.replace
router.prefetch
可能的解決方案
withRouter
如果 useRouter
不適合您的需求,withRouter
也可以將相同的 router
物件 添加到任何組件中。
使用方法
TypeScript
要將類組件與 withRouter
一起使用,組件需要接受一個 router 屬性: