Skip to content

Commit

Permalink
Upgrade to React Router v6 (#2919)
Browse files Browse the repository at this point in the history
  • Loading branch information
sandhose authored Jan 6, 2025
1 parent 46a82b2 commit b5f4a07
Show file tree
Hide file tree
Showing 19 changed files with 115 additions and 257 deletions.
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@
"@types/node": "^22.0.0",
"@types/pako": "^2.0.3",
"@types/qrcode": "^1.5.5",
"@types/react": "^18.3.0",
"@types/react-dom": "^18.3.0",
"@types/react-router-dom": "^5.3.3",
"@types/sdp-transform": "^2.4.5",
"@types/uuid": "10",
"@typescript-eslint/eslint-plugin": "^8.0.0",
Expand All @@ -82,7 +82,6 @@
"eslint-plugin-rxjs": "^5.0.3",
"eslint-plugin-unicorn": "^56.0.0",
"global-jsdom": "^25.0.0",
"history": "^4.0.0",
"i18next": "^23.0.0",
"i18next-browser-languagedetector": "^8.0.0",
"i18next-parser": "^9.0.0",
Expand All @@ -104,7 +103,7 @@
"react": "18",
"react-dom": "18",
"react-i18next": "^15.0.0",
"react-router-dom": "^5.2.0",
"react-router-dom": "^6.28.0",
"react-use-clipboard": "^1.0.7",
"react-use-measure": "^2.1.1",
"rxjs": "^7.8.1",
Expand Down
43 changes: 14 additions & 29 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,8 @@ Please see LICENSE in the repository root for full details.
*/

import { type FC, Suspense, useEffect, useState } from "react";
import {
BrowserRouter as Router,
Switch,
Route,
useLocation,
} from "react-router-dom";
import { BrowserRouter, Route, useLocation, Routes } from "react-router-dom";
import * as Sentry from "@sentry/react";
import { type History } from "history";
import { TooltipProvider } from "@vector-im/compound-web";
import { logger } from "matrix-js-sdk/src/logger";

Expand All @@ -29,7 +23,7 @@ import { MediaDevicesProvider } from "./livekit/MediaDevicesContext";
import { widget } from "./widget";
import { useTheme } from "./useTheme";

const SentryRoute = Sentry.withSentryRouting(Route);
const SentryRoute = Sentry.withSentryReactRouterV6Routing(Route);

interface SimpleProviderProps {
children: JSX.Element;
Expand All @@ -55,11 +49,7 @@ const ThemeProvider: FC<SimpleProviderProps> = ({ children }) => {
return children;
};

interface AppProps {
history: History;
}

export const App: FC<AppProps> = ({ history }) => {
export const App: FC = () => {
const [loaded, setLoaded] = useState(false);
useEffect(() => {
Initializer.init()
Expand All @@ -76,7 +66,7 @@ export const App: FC<AppProps> = ({ history }) => {
return (
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
<Router history={history}>
<BrowserRouter>
<BackgroundProvider>
<ThemeProvider>
<TooltipProvider>
Expand All @@ -86,20 +76,15 @@ export const App: FC<AppProps> = ({ history }) => {
<MediaDevicesProvider>
<Sentry.ErrorBoundary fallback={errorPage}>
<DisconnectedBanner />
<Switch>
<SentryRoute exact path="/">
<HomePage />
</SentryRoute>
<SentryRoute exact path="/login">
<LoginPage />
</SentryRoute>
<SentryRoute exact path="/register">
<RegisterPage />
</SentryRoute>
<SentryRoute path="*">
<RoomPage />
</SentryRoute>
</Switch>
<Routes>
<SentryRoute path="/" element={<HomePage />} />
<SentryRoute path="/login" element={<LoginPage />} />
<SentryRoute
path="/register"
element={<RegisterPage />}
/>
<SentryRoute path="*" element={<RoomPage />} />
</Routes>
</Sentry.ErrorBoundary>
</MediaDevicesProvider>
</ClientProvider>
Expand All @@ -110,6 +95,6 @@ export const App: FC<AppProps> = ({ history }) => {
</TooltipProvider>
</ThemeProvider>
</BackgroundProvider>
</Router>
</BrowserRouter>
);
};
8 changes: 4 additions & 4 deletions src/ClientContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
useRef,
useMemo,
} from "react";
import { useHistory } from "react-router-dom";
import { useNavigate } from "react-router-dom";
import { logger } from "matrix-js-sdk/src/logger";
import { useTranslation } from "react-i18next";
import { type ISyncStateData, type SyncState } from "matrix-js-sdk/src/sync";
Expand Down Expand Up @@ -144,7 +144,7 @@ interface Props {
}

export const ClientProvider: FC<Props> = ({ children }) => {
const history = useHistory();
const navigate = useNavigate();

// null = signed out, undefined = loading
const [initClientState, setInitClientState] = useState<
Expand Down Expand Up @@ -228,9 +228,9 @@ export const ClientProvider: FC<Props> = ({ children }) => {
await client.clearStores();
clearSession();
setInitClientState(null);
history.push("/");
navigate("/");
PosthogAnalytics.instance.setRegistrationType(RegistrationType.Guest);
}, [history, initClientState?.client]);
}, [navigate, initClientState?.client]);

const { t } = useTranslation();

Expand Down
2 changes: 1 addition & 1 deletion src/UserMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export const UserMenu: FC<Props> = ({

if (!isAuthenticated) {
return (
<LinkButton to={{ pathname: "/login", state: { from: location } }}>
<LinkButton to={{ pathname: "/login" }} state={{ from: location }}>
{t("log_in")}
</LinkButton>
);
Expand Down
8 changes: 4 additions & 4 deletions src/UserMenuContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Please see LICENSE in the repository root for full details.
*/

import { type FC, useCallback, useState } from "react";
import { useHistory, useLocation } from "react-router-dom";
import { useNavigate, useLocation } from "react-router-dom";

import { useClientLegacy } from "./ClientContext";
import { useProfile } from "./profile/useProfile";
Expand All @@ -19,7 +19,7 @@ interface Props {

export const UserMenuContainer: FC<Props> = ({ preventNavigation = false }) => {
const location = useLocation();
const history = useHistory();
const navigate = useNavigate();
const { client, logout, authenticated, passwordlessUser } = useClientLegacy();
const { displayName, avatarUrl } = useProfile(client);
const [settingsModalOpen, setSettingsModalOpen] = useState(false);
Expand All @@ -45,11 +45,11 @@ export const UserMenuContainer: FC<Props> = ({ preventNavigation = false }) => {
logout?.();
break;
case "login":
history.push("/login", { state: { from: location } });
navigate("/login", { state: { from: location } });
break;
}
},
[history, location, logout, setSettingsModalOpen],
[navigate, location, logout, setSettingsModalOpen],
);

const userName = client?.getUserIdLocalpart() ?? "";
Expand Down
10 changes: 5 additions & 5 deletions src/auth/LoginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Please see LICENSE in the repository root for full details.
*/

import { type FC, type FormEvent, useCallback, useRef, useState } from "react";
import { useHistory, useLocation } from "react-router-dom";
import { useNavigate, useLocation } from "react-router-dom";
import { Trans, useTranslation } from "react-i18next";
import { Button } from "@vector-im/compound-web";

Expand All @@ -29,7 +29,7 @@ export const LoginPage: FC = () => {
const homeserver = Config.defaultHomeserverUrl(); // TODO: Make this configurable
const usernameRef = useRef<HTMLInputElement>(null);
const passwordRef = useRef<HTMLInputElement>(null);
const history = useHistory();
const navigate = useNavigate();
const location = useLocation();
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error>();
Expand Down Expand Up @@ -61,9 +61,9 @@ export const LoginPage: FC = () => {
if (locationState && locationState.from) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
history.push(locationState.from);
navigate(locationState.from);
} else {
history.push("/");
navigate("/");
}
PosthogAnalytics.instance.eventLogin.track();
})
Expand All @@ -72,7 +72,7 @@ export const LoginPage: FC = () => {
setLoading(false);
});
},
[login, location, history, homeserver, setClient],
[login, location, navigate, homeserver, setClient],
);
// we need to limit the length of the homserver name to not cover the whole loginview input with the string.
let shortendHomeserverName = Config.defaultServerName()?.slice(0, 25);
Expand Down
14 changes: 7 additions & 7 deletions src/auth/RegisterPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
useRef,
useState,
} from "react";
import { useHistory, useLocation } from "react-router-dom";
import { useNavigate, useLocation } from "react-router-dom";
import { captureException } from "@sentry/react";
import { sleep } from "matrix-js-sdk/src/utils";
import { Trans, useTranslation } from "react-i18next";
Expand All @@ -41,7 +41,7 @@ export const RegisterPage: FC = () => {
useClientLegacy();

const confirmPasswordRef = useRef<HTMLInputElement>(null);
const history = useHistory();
const navigate = useNavigate();
const location = useLocation();
const [registering, setRegistering] = useState(false);
const [error, setError] = useState<Error>();
Expand Down Expand Up @@ -106,9 +106,9 @@ export const RegisterPage: FC = () => {
if (location.state?.from) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
history.push(location.state?.from);
navigate(location.state?.from);
} else {
history.push("/");
navigate("/");
}
})
.catch((error) => {
Expand All @@ -120,7 +120,7 @@ export const RegisterPage: FC = () => {
[
register,
location,
history,
navigate,
passwordlessUser,
reset,
execute,
Expand All @@ -141,9 +141,9 @@ export const RegisterPage: FC = () => {

useEffect(() => {
if (!loading && authenticated && !passwordlessUser && !registering) {
history.push("/");
navigate("/");
}
}, [loading, history, authenticated, passwordlessUser, registering]);
}, [loading, navigate, authenticated, passwordlessUser, registering]);

if (loading) {
return <LoadingView />;
Expand Down
29 changes: 7 additions & 22 deletions src/button/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,27 @@ import {
type ComponentPropsWithoutRef,
forwardRef,
type MouseEvent,
useCallback,
useMemo,
} from "react";
import { Link as CpdLink } from "@vector-im/compound-web";
import { useHistory } from "react-router-dom";
import { createPath, type LocationDescriptor, type Path } from "history";
import { type LinkProps, useHref, useLinkClickHandler } from "react-router-dom";
import classNames from "classnames";

import { useLatest } from "../useLatest";
import styles from "./Link.module.css";

export function useLink(
to: LocationDescriptor,
to: LinkProps["to"],
state?: unknown,
): [Path, (e: MouseEvent) => void] {
const latestState = useLatest(state);
const history = useHistory();
const path = useMemo(
() => (typeof to === "string" ? to : createPath(to)),
[to],
);
const onClick = useCallback(
(e: MouseEvent) => {
e.preventDefault();
history.push(to, latestState.current);
},
[history, to, latestState],
);
): [string, (e: MouseEvent<HTMLAnchorElement>) => void] {
const href = useHref(to);
const onClick = useLinkClickHandler(to, { state });

return [path, onClick];
return [href, onClick];
}

type Props = Omit<
ComponentPropsWithoutRef<typeof CpdLink>,
"href" | "onClick"
> & { to: LocationDescriptor; state?: unknown };
> & { to: LinkProps["to"]; state?: unknown };

/**
* A version of Compound's link component that integrates with our router setup.
Expand Down
8 changes: 4 additions & 4 deletions src/button/LinkButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@ Please see LICENSE in the repository root for full details.

import { type ComponentPropsWithoutRef, forwardRef } from "react";
import { Button } from "@vector-im/compound-web";
import { type LocationDescriptor } from "history";

import type { LinkProps } from "react-router-dom";
import { useLink } from "./Link";

type Props = Omit<
ComponentPropsWithoutRef<typeof Button<"a">>,
"as" | "href"
> & { to: LocationDescriptor };
> & { to: LinkProps["to"]; state?: unknown };

/**
* A version of Compound's button component that acts as a link and integrates
* with our router setup.
*/
export const LinkButton = forwardRef<HTMLAnchorElement, Props>(
function LinkButton({ to, ...props }, ref) {
const [path, onClick] = useLink(to);
function LinkButton({ to, state, ...props }, ref) {
const [path, onClick] = useLink(to, state);
return <Button as="a" ref={ref} {...props} href={path} onClick={onClick} />;
},
);
Loading

0 comments on commit b5f4a07

Please sign in to comment.