前言
useNavigation
是 React Router
中一個強大的鉤子,用于獲取當前頁面導航的狀態信息。
它可以幫助開發者根據導航狀態優化用戶體驗,如顯示加載指示器、防止重復提交等。
一、useNavigation核心用途
檢測導航狀態:判斷當前是否正在進行頁面導航或數據加載
防止用戶操作沖突:在導航過程中禁用表單提交按鈕
優化用戶體驗:在頁面加載期間顯示加載指示器
預加載感知:感知即將發生的導航并提前準備
二、useNavigation 基本用法
import { useNavigation } from "react-router-dom";function NavigationStatus() {const navigation = useNavigation();return (<div><p>當前導航狀態: {navigation.state}</p><p>目標路徑: {navigation.location?.pathname || "無"}</p></div>);
}
三、useNavigation 返回值詳解
useNavigation 返回一個包含以下屬性的對象:
四、useNavigation 導航狀態詳解
"idle"
:沒有導航活動
"loading"
:正在加載新頁面(頁面跳轉中)
"submitting"
:正在提交表單數據
五、useNavigation 完整代碼案例
5.1、全局加載指示器
import { useNavigation } from "react-router-dom";function GlobalLoadingIndicator() {const navigation = useNavigation();// 當有導航活動時顯示加載指示器const isLoading = navigation.state !== "idle";return isLoading ? (<div className="loading-overlay"><div className="spinner"></div>{navigation.state === "submitting" && (<p>提交數據中...</p>)}{navigation.state === "loading" && (<p>加載頁面中...</p>)}</div>) : null;
}
5.2、表單提交狀態管理
import { useNavigation } from "react-router-dom";function SubmitButton() {const navigation = useNavigation();const isSubmitting = navigation.state === "submitting";return (<button type="submit" disabled={isSubmitting}className={isSubmitting ? "submitting" : ""}>{isSubmitting ? "提交中..." : "提交表單"}</button>);
}function ContactForm() {return (<form method="post" action="/contact"><input type="text" name="name" placeholder="姓名" required /><input type="email" name="email" placeholder="郵箱" required /><textarea name="message" placeholder="留言" rows={4} required /><SubmitButton /></form>);
}
5.3、基于導航狀態優化用戶體驗
import { useNavigation } from "react-router-dom";function ProductPage() {const navigation = useNavigation();// 當即將導航到新頁面時,顯示骨架屏const isNavigating = navigation.state === "loading";const targetIsProduct = navigation.location?.pathname?.startsWith("/product/");return (<div className="product-container">{isNavigating && targetIsProduct ? (<ProductSkeleton />) : (<ProductDetails />)}<RelatedProducts />{/* 在提交評論時禁用評論表單 */}<CommentForm disabled={navigation.state === "submitting"} /></div>);
}function ProductSkeleton() {return (<div className="skeleton"><div className="skeleton-image"></div><div className="skeleton-title"></div><div className="skeleton-description"></div></div>);
}
六、useNavigation 高級用法:預加載感知
import { useNavigation, Link } from "react-router-dom";function ProductList({ products }) {const navigation = useNavigation();// 獲取即將導航到的產品IDconst nextProductId = navigation.location?.pathname?.split("/")[2];return (<div><h2>產品列表</h2><ul>{products.map(product => (<li key={product.id}><Link to={`/product/${product.id}`}>{product.name}{/* 高亮即將訪問的產品 */}{nextProductId === product.id && " (正在加載...)"}</Link></li>))}</ul></div>);
}
七、useNavigation
與相似鉤子的對比
鉤子 用途 返回信息
useNavigation
:用于 獲取當前導航狀態、目標位置等
useLocation
:用于 獲取當前URL信息,返回信息包含:當前路徑、查詢參數等
useNavigate
:用于 編程式導航,返回:導航函數
useLoaderData
:用于 獲取路由加載器提供的數據,返回: 加載的數據
useActionData
: 用于 獲取表單提交后返回的數據,返回: 動作返回的數據
八、注意事項
8.1、理解狀態變化:
"submitting" → "loading" → "idle"
是典型的狀態變化流程
表單提交后會立即跳轉到新頁面
8.2、避免過度使用:
只在需要響應導航狀態的組件中使用
避免在性能敏感
的組件中使用
8.3、與數據加載的配合:
useNavigation
關注導航狀態
useLoaderData
關注數據加載結果
兩者可以配合使用優化加載體驗
8.4、錯誤處理:
function SmartButton() {const navigation = useNavigation();const actionData = useActionData();const isSubmitting = navigation.state === "submitting";const hasError = actionData?.error;return (<button type="submit" disabled={isSubmitting || hasError}>{isSubmitting ? "處理中..." : "提交"}</button>);
}
九、最佳實踐
9.1、 創建導航感知組件
function NavigationAwareLink({ to, children }) {const navigation = useNavigation();const isActive = navigation.location?.pathname === to;const isNavigatingTo = navigation.state === "loading" && navigation.location?.pathname === to;return (<Link to={to} className={`nav-link ${isActive ? "active" : ""} ${isNavigatingTo ? "navigating" : ""}`}>{children}{isNavigatingTo && <span className="loading-dot"></span>}</Link>);
}
9.2、 結合 Suspense
優化加載體驗
import { useNavigation } from "react-router-dom";
import { Suspense } from "react";function Dashboard() {const navigation = useNavigation();return (<div><h1>控制面板</h1><Suspense fallback={<Spinner />}>{navigation.state === "idle" ? (<DashboardContent />) : (<DashboardSkeleton />)}</Suspense></div>);
}
總結
useNavigation
是 React Router
中用于增強用戶體驗的關鍵鉤子,通過它開發者可以:
1.精確感知導航狀態(空閑、加載中、提交中
)
2.根據狀態動態調整 UI
(顯示加載指示器、禁用按鈕等)
3.提前預知用戶
即將訪問的頁面
4.創建更加流暢的導航體驗
合理使用 useNavigation
可以顯著提升應用的交互質量和用戶滿意度,特別是在需要處理異步操作和頁面過渡的場景中。