Skip to content

Commit

Permalink
add useDocumentTitle hook
Browse files Browse the repository at this point in the history
  • Loading branch information
imbhargav5 committed Apr 10, 2023
1 parent b74a920 commit d12aa96
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 0 deletions.
84 changes: 84 additions & 0 deletions data/docs/useDocumentTitle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
id: useDocumentTitle
title: useDocumentTitle
sidebar_label: useDocumentTitle
---

## About

Sets the document title and optionally resets the title on unmount

[//]: # "Main"

## Examples

### Basic example

````jsx
import { useDocumentTitle } from "rooks";

function App() {
useDocumentTitle("New document title");

return (
<div>
<h1>Document title is now "New document title"</h1>
</div>
);
}

export default App;


## Examples

### Basic example

```jsx
import { useDocumentTitle } from "rooks";
function App() {
useDocumentTitle("New document title");
return (
<div>
<h1>Document title is now "New document title"</h1>
</div>
);
}
export default App;
````
### Example with reset
```jsx
import { useDocumentTitle } from "rooks";

function App() {
useDocumentTitle("New document title", { resetOnUnmount: true });

return (
<div>
<h1>
Document title is now "New document title" and will be reset on unmount
</h1>
</div>
);
}

export default App;
```

## Arguments

| Argument | Type | Description |
| :--------------------- | :-------- | :--------------------------------------------- |
| title | `string` | The new document title |
| options | `object` | Options object |
| options.resetOnUnmount | `boolean` | Whether to reset the document title on unmount |

## Return

`void`
5 changes: 5 additions & 0 deletions data/hooks-list.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@
"description": "A react hook to an event listener to the document object",
"category": "events"
},
{
"name": "useDocumentTitle",
"description": "A hook to easily update document title with React",
"category": "effects"
},
{
"name": "useDocumentVisibilityState",
"description": "Returns the visibility state of the document.",
Expand Down
65 changes: 65 additions & 0 deletions packages/rooks/src/__tests__/useDocumentTitle.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { renderHook } from "@testing-library/react-hooks";
import { useDocumentTitle } from "@/hooks/useDocumentTitle";

describe("useDocumentTitle", () => {
// Mock window.document.title
Object.defineProperty(window.document, "title", {
value: "",
writable: true,
});

it("should set document title", () => {
expect.hasAssertions();
const { rerender } = renderHook(({ title }) => useDocumentTitle(title), {
initialProps: { title: "Initial Title" },
});

expect(document.title).toBe("Initial Title");

rerender({ title: "Updated Title" });

expect(document.title).toBe("Updated Title");
});

it("should reset document title when resetOnUnmount is true", () => {
expect.hasAssertions();
// Set an initial document title
const initialTitle = "Initial Title";
document.title = initialTitle;

const { unmount } = renderHook(
({ title, options }) => useDocumentTitle(title, options),
{
initialProps: {
title: "Title with Reset",
options: { resetOnUnmount: true },
},
}
);

expect(document.title).toBe("Title with Reset");

unmount();

expect(document.title).toBe(initialTitle);
});

it("should not reset document title when resetOnUnmount is false or not provided", () => {
expect.hasAssertions();
const { unmount } = renderHook(
({ title, options }) => useDocumentTitle(title, options),
{
initialProps: {
title: "Title without Reset",
options: { resetOnUnmount: false },
},
}
);

expect(document.title).toBe("Title without Reset");

unmount();

expect(document.title).toBe("Title without Reset");
});
});
49 changes: 49 additions & 0 deletions packages/rooks/src/hooks/useDocumentTitle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* useDocumentTitle
* @description A hook to easily update document title with React
*/
import { noop } from "lodash";
import { useEffect, useRef } from "react";

type UseDocumentTitleOptions = {
resetOnUnmount?: boolean;
};

/**
* useDocumentTitle hook
*
* This hook allows you to set the document title.
*
* @param title - The new title for the document
* @param options - An optional object with a `resetOnUnmount` property to control whether the document title should be reset to its previous value when the component is unmounted. Defaults to false.
*
* @example
* function App() {
* useDocumentTitle("My App", { resetOnUnmount: true });
* return <div>Hello, world!</div>;
* }
* @see {@link https://rooks.vercel.app/docs/useDocumentTitle}
*/
function useDocumentTitle(
title: string,
options: UseDocumentTitleOptions = {}
): void {
const isBrowser = typeof window !== "undefined";
const prevTitleRef = useRef(isBrowser ? document.title : "");
const { resetOnUnmount = false } = options;

useEffect(() => {
if (isBrowser) {
document.title = title;
const lastTitle = prevTitleRef.current;
if (resetOnUnmount) {
return () => {
document.title = lastTitle;
};
}
}
return noop;
}, [title, isBrowser, resetOnUnmount]);
}

export { useDocumentTitle };
1 change: 1 addition & 0 deletions packages/rooks/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export { useDidMount } from "@/hooks/useDidMount";
export { useDidUpdate } from "@/hooks/useDidUpdate";
export { useDimensionsRef } from "@/hooks/useDimensionsRef";
export { useDocumentEventListener } from "@/hooks/useDocumentEventListener";
export { useDocumentTitle } from "@/hooks/useDocumentTitle";
export { useDocumentVisibilityState } from "@/hooks/useDocumentVisibilityState";
export { useEffectOnceWhen } from "@/hooks/useEffectOnceWhen";
export { useEventListenerRef } from "@/hooks/useEventListenerRef";
Expand Down

0 comments on commit d12aa96

Please sign in to comment.