routeNotFound.tsx 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import {useLayoutEffect} from 'react';
  2. import type {RouteComponentProps} from 'react-router';
  3. import * as Sentry from '@sentry/react';
  4. import NotFound from 'sentry/components/errors/notFound';
  5. import Footer from 'sentry/components/footer';
  6. import * as Layout from 'sentry/components/layouts/thirds';
  7. import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
  8. import Sidebar from 'sentry/components/sidebar';
  9. import {t} from 'sentry/locale';
  10. type Props = RouteComponentProps<{}, {}>;
  11. function RouteNotFound({router, location}: Props) {
  12. const {pathname, search, hash} = location;
  13. const isMissingSlash = pathname[pathname.length - 1] !== '/';
  14. useLayoutEffect(() => {
  15. // Attempt to fix trailing slashes first
  16. if (isMissingSlash) {
  17. router.replace(`${pathname}/${search}${hash}`);
  18. return;
  19. }
  20. Sentry.withScope(scope => {
  21. scope.setFingerprint(['RouteNotFound']);
  22. scope.setTag('isMissingSlash', isMissingSlash);
  23. scope.setTag('pathname', pathname);
  24. Sentry.captureException(new Error('Route not found'));
  25. });
  26. }, [pathname, search, hash, isMissingSlash, router]);
  27. if (isMissingSlash) {
  28. return null;
  29. }
  30. return (
  31. <SentryDocumentTitle title={t('Page Not Found')}>
  32. <div className="app">
  33. <Sidebar />
  34. <Layout.Page withPadding>
  35. <NotFound />
  36. </Layout.Page>
  37. <Footer />
  38. </div>
  39. </SentryDocumentTitle>
  40. );
  41. }
  42. export default RouteNotFound;