next.js 元数据标题模板链接

问题描述 投票:0回答:1

我正在开发一个具有嵌套文件结构的 Next.js 项目,我希望每个布局级别递归地添加标题前缀,因此最终标题是直到当前页面的所有布局标题的组合。

这是我的文件夹结构:

├── app
│   ├── layout.tsx     // Title "Studio"      
│   ├── project-review
│   │   ├── layout.tsx     // Title "Studio - Project Review"  
│   │   ├── history
│   │   │   └── page.tsx       // // Title "Studio - Project Review - history"
│   │   └── page.tsx
│   └── page.tsx

在我的根布局.tsx 中,我设置了基本标题模板:

// app/layout.tsx
export const metadata = {
  title: { template: 'Studio - %s', default: 'Studio' },
};

在下一个文件中:

// app/project-review/layout.tsx
export const metadata = {
  title: { template: 'Project Review - %s', default: 'Project reviews' },
};

// app/project-review/history/page.tsx
export const metadata = {
  title: { default: 'History' },
};

我需要将标题 teplmate 中的值链接到所有嵌套布局

通过此设置,显示的标题为项目回顾 - 历史记录,而不是 Studio - 项目回顾 - 历史记录。布局中的每个元数据对象似乎都会替换而不是附加到先前的元数据,因此仅使用最近的标题模板。

为什么这种方法不能满足我的需求

我的目标是让 Next.js 自动组合嵌套布局中的标题,而无需在每个布局中手动连接它们。这将允许采用可扩展的方法来管理复杂的页面标题,这些标题动态地反映我的应用程序的结构,其中每个布局都有自己独特的前缀。

有没有办法在 Next.js 中使用元数据实现递归标题模板,或者我需要一个自定义解决方案来手动处理这种继承吗?

reactjs typescript next.js metadata
1个回答
0
投票

元数据仅影响其正下方的页面,这解释了为什么最近的标题模板会覆盖前面的页面。

但是您可以使用 Context 来跟踪标题,请参阅下面的示例

首先,在应用程序文件夹中创建一个上下文文件(TitleContext.tsx)

import React, { createContext, useContext, useMemo } from 'react';

const TitleContext = createContext<string[]>([]);

export const useTitleSegments = () => useContext(TitleContext);

export const TitleProvider = ({ segment, children }: { segment: string, children: React.ReactNode }) => {
  const parentSegments = useTitleSegments();
  const segments = useMemo(() => [...parentSegments, segment], [parentSegments, segment]);

  return (
    <TitleContext.Provider value={segments}>
      {children}
    </TitleContext.Provider>
  );
};

然后更新您的 layout.tsx 将子项包装在标题提供程序中

import { TitleProvider } from './TitleContext';

export const metadata = {
  title: { template: 'Studio - %s', default: 'Studio' },
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <TitleProvider segment="Studio">
      {children}
    </TitleProvider>
  );
}

接下来在各个页面布局页面中一起添加标题,例如 project-review/history/page.tsx

import { useTitleSegments } from '../../TitleContext';

export const metadata = {
  title: { default: 'History' },
};

export default function HistoryPage() {
  const titleSegments = useTitleSegments();
  const title = titleSegments.join(' - '); // "Studio - Project Review - History"

  // Use this title for dynamic head or pass it as metadata if needed.
  return (
    <>
      <head>
        <title>{title}</title>
      </head>
      <main>
        <h1>{title}</h1>
        {/* Page content */}
      </main>
    </>
  );
}

© www.soinside.com 2019 - 2024. All rights reserved.