Initial commit
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
# usePageMeta
|
||||
|
||||
Sets the page `<title>` and/or `<meta name="description">` while a component is mounted, then restores the previous values on unmount.
|
||||
|
||||
## Signature
|
||||
|
||||
```ts
|
||||
function usePageMeta(params: UsePageMetaParams): void;
|
||||
|
||||
interface UsePageMetaParams {
|
||||
title?: string;
|
||||
description?: string;
|
||||
}
|
||||
```
|
||||
|
||||
| Param | Type | Description |
|
||||
| ------------- | -------- | ------------------------------------------- |
|
||||
| `title` | `string` | Value to set as `document.title` |
|
||||
| `description` | `string` | Value to set in `<meta name="description">` |
|
||||
|
||||
Both params are optional — pass only the ones you need.
|
||||
|
||||
## Usage
|
||||
|
||||
```tsx
|
||||
function ArticlePage({ article }: { article: Article }) {
|
||||
usePageMeta({
|
||||
title: article.title,
|
||||
description: article.summary,
|
||||
});
|
||||
|
||||
return <main>{article.content}</main>;
|
||||
}
|
||||
```
|
||||
|
||||
```tsx
|
||||
// Title only
|
||||
function DashboardPage() {
|
||||
usePageMeta({ title: 'Dashboard' });
|
||||
return <div />;
|
||||
}
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Restores the previous `document.title` and `<meta>` content when the component unmounts, so nested or sequential usage is safe.
|
||||
- If no `<meta name="description">` tag exists in the document, one is created and removed on cleanup.
|
||||
- Client-only (`'use client'`). Does not run during SSR.
|
||||
@@ -0,0 +1 @@
|
||||
export * from './usePageMeta';
|
||||
@@ -0,0 +1,45 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export interface UsePageMetaParams {
|
||||
title?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export function usePageMeta({ title, description }: UsePageMetaParams) {
|
||||
useEffect(() => {
|
||||
if (!title) return;
|
||||
|
||||
const previousTitle = document.title;
|
||||
document.title = title;
|
||||
|
||||
return () => {
|
||||
document.title = previousTitle;
|
||||
};
|
||||
}, [title]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!description) return;
|
||||
|
||||
let tag = document.querySelector<HTMLMetaElement>('meta[name="description"]');
|
||||
|
||||
const created = !tag;
|
||||
if (!tag) {
|
||||
tag = document.createElement('meta');
|
||||
tag.name = 'description';
|
||||
document.head.appendChild(tag);
|
||||
}
|
||||
|
||||
const previousContent = tag.content;
|
||||
tag.content = description;
|
||||
|
||||
return () => {
|
||||
if (created) {
|
||||
tag.remove();
|
||||
} else {
|
||||
tag.content = previousContent;
|
||||
}
|
||||
};
|
||||
}, [description]);
|
||||
}
|
||||
Reference in New Issue
Block a user