sentryDocumentTitle.tsx 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import {createContext, useContext, useEffect, useMemo} from 'react';
  2. type Props = {
  3. children?: React.ReactNode;
  4. /**
  5. * Should the ` - Sentry` suffix be excluded?
  6. */
  7. noSuffix?: boolean;
  8. /**
  9. * The organization slug to show in the title
  10. */
  11. orgSlug?: string;
  12. /**
  13. * The project slug to show in the title.
  14. */
  15. projectSlug?: string;
  16. /**
  17. * This string will be shown at the very front of the title
  18. */
  19. title?: string;
  20. };
  21. const DEFAULT_PAGE_TITLE = 'Sentry';
  22. const DocumentTitleContext = createContext(DEFAULT_PAGE_TITLE);
  23. /**
  24. * Assigns the document title. The deepest nested version of this title will be
  25. * the one which is assigned.
  26. */
  27. function SentryDocumentTitle({
  28. title = '',
  29. orgSlug,
  30. projectSlug,
  31. noSuffix,
  32. children,
  33. }: Props) {
  34. const parentTitle = useContext(DocumentTitleContext);
  35. const pageTitle = useMemo(() => {
  36. if (orgSlug && projectSlug) {
  37. return `${title} — ${orgSlug} — ${projectSlug}`;
  38. }
  39. if (orgSlug) {
  40. return `${title} — ${orgSlug}`;
  41. }
  42. if (projectSlug) {
  43. return `${title} — ${projectSlug}`;
  44. }
  45. return title;
  46. }, [orgSlug, projectSlug, title]);
  47. const documentTitle = useMemo(() => {
  48. if (noSuffix) {
  49. return pageTitle;
  50. }
  51. if (pageTitle !== '') {
  52. return `${pageTitle} — Sentry`;
  53. }
  54. return DEFAULT_PAGE_TITLE;
  55. }, [noSuffix, pageTitle]);
  56. // NOTE: We do this OUTSIDE of a use effect so that the update order is
  57. // correct, otherwsie the inner most SentryDocumentTitle will have its
  58. // useEffect called first followed by the parents, which will cause the wrong
  59. // title be set.
  60. if (document.title !== documentTitle) {
  61. document.title = documentTitle;
  62. }
  63. useEffect(() => {
  64. return () => {
  65. document.title = parentTitle;
  66. };
  67. }, [parentTitle]);
  68. return (
  69. <DocumentTitleContext.Provider value={documentTitle}>
  70. {children}
  71. </DocumentTitleContext.Provider>
  72. );
  73. }
  74. export default SentryDocumentTitle;