Skip to content

How to show the notification count in the page title

This example demonstrates how to show the notification count in the page title using the useTitle hook. It includes code in both TypeScript and JavaScript versions.

TypeScript version

Watch the live preview.

tsx
import { useEffect, useState } from "react";
import { useTitle } from "./useTitle";

interface Notification {
  id: number;
  title: string;
}

const appNotifications: Notification[] = [
  { id: 1, title: "Notification 1" },
  { id: 2, title: "Notification 2" },
  { id: 3, title: "Notification 3" },
  { id: 4, title: "Notification 4" },
  { id: 5, title: "Notification 5" },
];

export default function App() {
  const [notifications, setNotifications] =
    useState<Notification[]>(appNotifications);
  const { title, changeTitle } = useTitle();

  useEffect(() => {
    changeTitle(`${title} (${notifications.length})`);
  }, []);

  // Delete notification
  const deleteNotification = (id: number) => {
    const updatedNotifications = notifications.filter(
      (notification) => notification.id !== id
    );
    setNotifications(updatedNotifications);

    // Set the title depending on the number of notifications left
    const newTitle =
      updatedNotifications.length > 0
        ? `${title.split(" (")[0]} (${updatedNotifications.length})`
        : title.split(" (")[0];
    changeTitle(newTitle);
  };

  return (
    <>
      <h1>Notifications</h1>
      <ul>
        {notifications.map((notification) => (
          <li key={notification.id}>
            {notification.title}
            <button onClick={() => deleteNotification(notification.id)}>
              Delete
            </button>
          </li>
        ))}
      </ul>
    </>
  );
}
typescript
import { useState } from "react";

export const useTitle = () => {
  const [title, setTitle] = useState<string>(document.title);

  const changeTitle = (newTitle: string) => {
    document.title = newTitle;
    setTitle(newTitle);
  };

  return { title, changeTitle };
};

JavaScript version

Watch the live preview.

jsx
import { useEffect, useState } from "react";
import { useTitle } from "./useTitle.js";

const appNotifications = [
  { id: 1, title: "Notification 1" },
  { id: 2, title: "Notification 2" },
  { id: 3, title: "Notification 3" },
  { id: 4, title: "Notification 4" },
  { id: 5, title: "Notification 5" },
];

export default function App() {
  const [notifications, setNotifications] = useState(appNotifications);
  const { title, changeTitle } = useTitle();

  useEffect(() => {
    changeTitle(`${title} (${notifications.length})`);
  }, []);

  // Delete notification
  const deleteNotification = (id) => {
    const updatedNotifications = notifications.filter(
      (notification) => notification.id !== id
    );
    setNotifications(updatedNotifications);

    // Set the title depending on the number of notifications left
    const newTitle =
      updatedNotifications.length > 0
        ? `${title.split(" (")[0]} (${updatedNotifications.length})`
        : title.split(" (")[0];
    changeTitle(newTitle);
  };

  return (
    <>
      <h1>Notifications</h1>
      <ul>
        {notifications.map((notification) => (
          <li key={notification.id}>
            {notification.title}
            <button onClick={() => deleteNotification(notification.id)}>
              Delete
            </button>
          </li>
        ))}
      </ul>
    </>
  );
}
javascript
import { useState } from "react";

export const useTitle = () => {
  const [title, setTitle] = useState(document.title);

  const changeTitle = (newTitle) => {
    document.title = newTitle;
    setTitle(newTitle);
  };

  return { title, changeTitle };
};

Released under the MIT License.