在 Next.js 中,如何创建“模态链接”(即更改 URL 并添加组件但不重新渲染整个页面的链接)

mac*_*ost 12 routes next.js

当一个站点有一个对话框时,它通常纯粹用 JS 完成,不涉及“页面”(即路由)。但是,有时您希望对话框有自己的 URL,以便在用户刷新页面时,他们会返回到对话框打开的页面。

在 Next.js 中,我已经完成了上述大部分工作。我有一个基本页面路由,然后是呈现该页面组件的第二个路由,以及我的对话框组件。当我单击链接时,它会更改 URL,然后我会看到我的对话框...如果我刷新,我仍然会看到该页面/对话框。

但是,当我第一次单击该链接时,它会重新呈现页面,从而丢失其他状态更改。我认为shallow在链接上使用 prop 会阻止这种情况,但事实并非如此(我猜是因为对话路由是不同的路由,而不仅仅是查询参数?)。我还认为也许使用as而不是href会起作用......但事实证明这href是必需的。

因此,总而言之,是否可以在 Next.js 中创建一个链接:

  1. 确实更改了 URL(更改为实际页面,而不仅仅是查询参数)
  2. 渲染一个新的(对话框)组件
  3. 重新渲染主页面组件

PS 我正在从 Gatsby 移植一个网站,这可能的,虽然我可以更改我的路线以使用查询参数而不是真实路线,但这将有效地“删除”我网站上的一堆页面......从而产生 SEO 后果:(

mac*_*ost 13

这是我想出的使这项工作有效的模式。

步骤#1:制作主页(带有可选对话框)

创建您的(例如,pages/todo/[pageId].js对于待办事项应用程序)页面。它的默认导出应该是一个使用 Next 路由器来决定是否显示对话框的组件。

例如,如果您的模态框要添加/modal/5到 URL(以显示模态框 #5),您可以执行以下操作:

data => {
  const router = useRouter();
  const { modal } = router.query;

  return (
    <>
      <Page {...data} />
      {modal ? (<Dialog {...data} />) : null}
    </>
  );
Run Code Online (Sandbox Code Playgroud)

<body>(注意:如果需要,通过使用 React“门户”,您仍然可以直接在元素下渲染对话框。)

步骤#1.5:使页面动态导出功能

同时,getStaticProps正常进行导出。还创建一个getStaticPaths,但在其中您希望为每个页面返回两个路径对象:一个包含对话框的参数,另一个将该参数设置为空字符串。这告诉 Next.js 该页面可以具有打开/关闭这两种 URL 状态。

例如,如果您的页面是,/todo/1并且您有一个模式 #3 的“模式”参数的链接,那么您将拥有一个“模式 URL” /todo/1/modal/3。您需要返回该路径一个/todo/1.

步骤#2:建立链接

这部分有点棘手;你希望你的链接看起来像这样:

<Link
    as={`/todo/${pageId}/modal/${modalId}`}
    href={{
      pathname: `/todo/[pageId]?modalId=[modalId]`,
      query: { pageId, modalId },
    }}
    scroll={false}
    shallow={true}
  >
    Click me to open dialog
</Link>
Run Code Online (Sandbox Code Playgroud)

换句话说,该asprop 将是您的模态 URL,单击链接时,Next 会将地址栏更改为该 URL。但它实际上会使用该href对象,该对象用于带有页面/模式 ID 查询参数的非模式 URL。它必须使用查询参数来保持核心 URL 相同。

最后,我们设置scroll链接false不会滚动到页面顶部,shallowtrue避免重新获取无意义的数据。完成所有这些后,一切都会正常......除非您在打开对话框的情况下刷新页面。

这是因为as只是伪造了 URL,而我们实际上并没有为其制定路由

步骤#3:制作模态“页面”

在正确的目录结构中创建一个页面文件(例如/todo/[pageId]/modal/[modalId].js)...但是这个文件将非常简单。事实上,您甚至可以getStaticProps从主页上重复使用您的组件!

export {
  default,
  getStaticProps,
} from 'pages/todo/[pageId]';
Run Code Online (Sandbox Code Playgroud)

不过,您将需要制作一个新版本getStaticPaths。它将与主页第一页相同,只是它只会为每个路径返回一个路径对象(ID 中带有模态参数的路径对象)。