/ src / utils / useTitle.js
useTitle.js
 1  import { useLayoutEffect } from 'preact/hooks';
 2  import { matchPath } from 'react-router-dom';
 3  import { subscribeKey } from 'valtio/utils';
 4  
 5  import states from './states';
 6  
 7  const { VITE_CLIENT_NAME: CLIENT_NAME } = import.meta.env;
 8  
 9  export default function useTitle(title, path) {
10    function setTitle() {
11      const { currentLocation } = states;
12      const hasPaths = Array.isArray(path);
13      let paths = hasPaths ? path : [];
14      // Workaround for matchPath not working for optional path segments
15      // https://github.com/remix-run/react-router/discussions/9862
16      if (!hasPaths && /:?\w+\?/.test(path)) {
17        paths.push(path.replace(/(:\w+)\?/g, '$1'));
18        paths.push(path.replace(/\/?:\w+\?/g, ''));
19      }
20      let matched = false;
21      if (paths.length) {
22        matched = paths.some((p) => matchPath(p, currentLocation));
23      } else if (path) {
24        matched = matchPath(path, currentLocation);
25      }
26      console.debug('setTitle', { title, path, currentLocation, paths, matched });
27      if (matched) {
28        document.title = title ? `${title} / ${CLIENT_NAME}` : CLIENT_NAME;
29      }
30    }
31  
32    useLayoutEffect(() => {
33      const unsub = subscribeKey(states, 'currentLocation', setTitle);
34      setTitle();
35      return unsub;
36    }, [title, path]);
37  }