Next.js - 浅层路由
Next.js - 浅路由
Section titled “Next.js - 浅路由”**浅路由(Shallow routing)**是 Next.js 中一个特定于 Pages Router 的功能。它允许你改变 URL 路径(包括查询参数),而无需重新运行 getServerSideProps、getStaticProps 或 getInitialProps 等数据获取方法。
当你只需要更新 URL 以反映客户端已有的状态时,此功能非常有用,例如在 URL 中跟踪过滤器、选项卡或分页状态,而无需触发完整的服务器端数据重新获取。
注意:由于 App Router 的架构不同,它专注于 Server Components 和 React Server Actions,URL 更新通常会自然地触发服务器端逻辑或按需的特定组件重新渲染,因此浅路由的概念在其中关联性较低。
要在 Pages Router 中执行浅路由,你可以使用 useRouter hook 的 router.push 或 router.replace 方法,并传递 shallow: true 选项。
让我们更新一个示例页面(例如,pages/index.js)来演示浅路由。假设此页面使用 getServerSideProps 来获取一些初始数据。
import { useRouter } from 'next/router';import Head from 'next/head';import { useEffect, useState } from 'react';
function HomePage(props) { const router = useRouter(); // 我们希望在 URL 中反映的示例客户端状态 const [counter, setCounter] = useState(0);
// 在初次加载/路由改变时,根据 URL 查询参数更新计数器状态 useEffect(() => { if (router.query.counter) { setCounter(parseInt(router.query.counter, 10) || 0); } }, [router.query.counter]);
const handleIncrement = () => { const newCounter = counter + 1; setCounter(newCounter); // 更新 URL 查询参数,但无需重新运行 getServerSideProps router.push(`/?counter=${newCounter}`, undefined, { shallow: true }); };
return ( <> <Head> <title>Welcome to Next.js! (Shallow Routing)</title> </Head> <div> <h1>Welcome to Next.js!</h1> <p>演示浅路由</p> <p>初始星标数 (来自 getServerSideProps): {props.stars}</p> <p>客户端计数器: {counter}</p> <button onClick={handleIncrement}>增加计数器 (浅更新 URL)</button> <br /> <p>当前 URL 查询参数: {JSON.stringify(router.query)}</p> <p>(请检查你的浏览器控制台日志,看点击按钮时是否运行了 getServerSideProps)</p> </div> </> );}
export async function getServerSideProps(context) { console.log('getServerSideProps executed!'); // 记录日志以查看何时运行 // 示例:获取仅应在初次导航或完全刷新时加载的数据 const res = await fetch('https://api.github.com/repos/vercel/next.js'); const json = await res.json(); return { props: { stars: json.stargazers_count || 'N/A' }, };}
export default HomePage;在这个例子中:
- 我们使用
getServerSideProps来获取 GitHub 星标数,并在它运行时记录日志到控制台。 - 我们维护一个客户端的
counter状态。 - 一个
useEffecthook 会在 URL 中存在?counter=查询参数时同步counter状态。 handleIncrement函数会更新客户端状态,然后使用带有{ shallow: true }选项的router.push将新的计数器值追加到 URL 的查询字符串中。
运行开发服务器
Section titled “运行开发服务器”如果服务器未运行,请启动它:
npm run dev
# Example Output:# ready - started server on 0.0.0.0:3000, url: http://localhost:3000# event - compiled client and server successfully ...-
在浏览器中打开
http://localhost:3000。检查你的服务器控制台(运行npm run dev的地方)。你应该看到 ‘getServerSideProps executed!’ 的日志消息。 -
多次点击 ‘增加计数器 (浅更新 URL)’ 按钮。
-
观察以下现象:
- 页面上显示的计数器值增加。
- 浏览器地址栏中的 URL 更新(例如,
/?counter=1、/?counter=2等)。 - 再次检查你的服务器控制台。在点击按钮后,你不应该看到 ‘getServerSideProps executed!’ 的日志消息。这确认了数据获取函数没有重新运行,这要归功于
shallow: true。
-
刷新页面(例如,当 URL 是
/?counter=3时)。现在,你会在服务器控制台看到 ‘getServerSideProps executed!’,因为发生了一次完整的页面加载。然后,useEffecthook 将从router.query读取counter=3,并相应地设置初始的客户端计数器状态。