From 18e3a16299eb79df2edd6a425ee758679a832b70 Mon Sep 17 00:00:00 2001
From: Trevor Farlow <trevdor@users.noreply.github.com>
Date: Sat, 20 May 2023 16:01:10 -0600
Subject: [PATCH] Update to React Router v5.1 conventions (#1045)

---
 .../src/components/FinancesApp.js             | 183 ++++++-------
 .../desktop-client/src/components/Modals.js   | 246 +++++++-----------
 .../desktop-client/src/components/Titlebar.js |  84 +++---
 .../src/components/accounts/Account.js        |  26 +-
 .../src/components/accounts/MobileAccount.js  |   8 +-
 .../src/components/manager/ManagementApp.js   |  54 ++--
 .../src/components/modals/ManageRulesModal.js |   2 +-
 .../src/components/reports/index.js           |  12 +-
 upcoming-release-notes/1045.md                |   6 +
 9 files changed, 267 insertions(+), 354 deletions(-)
 create mode 100644 upcoming-release-notes/1045.md

diff --git a/packages/desktop-client/src/components/FinancesApp.js b/packages/desktop-client/src/components/FinancesApp.js
index 6ec499df2..74e592dd7 100644
--- a/packages/desktop-client/src/components/FinancesApp.js
+++ b/packages/desktop-client/src/components/FinancesApp.js
@@ -57,118 +57,82 @@ import PostsOfflineNotification from './schedules/PostsOfflineNotification';
 import Settings from './settings';
 import Titlebar, { TitlebarProvider } from './Titlebar';
 
-function PageRoute({
-  path,
-  component: Component,
-  redirectTo = '/budget',
-  worksInNarrow = true,
-}) {
+function NarrowNotSupported({ children, redirectTo = '/budget' }) {
   const { isNarrowWidth } = useResponsive();
-  return worksInNarrow || !isNarrowWidth ? (
-    <Route
-      path={path}
-      children={props => {
-        return (
-          <View
-            style={{
-              flex: 1,
-              display: props.match ? 'flex' : 'none',
-            }}
-          >
-            <Component {...props} />
-          </View>
-        );
-      }}
-    />
-  ) : (
-    <Redirect to={redirectTo} />
-  );
-}
-
-function NonPageRoute({
-  redirectTo = '/budget',
-  worksInNarrow = true,
-  ...routeProps
-}) {
-  const { isNarrowWidth } = useResponsive();
-
-  return worksInNarrow || !isNarrowWidth ? (
-    <Route {...routeProps} />
-  ) : (
-    <Redirect to={redirectTo} />
-  );
+  return isNarrowWidth ? <Redirect to={redirectTo} /> : children;
 }
 
 function Routes({ location }) {
   const { isNarrowWidth } = useResponsive();
   return (
     <Switch location={location}>
-      <Redirect from="/" exact to="/budget" />
-
-      <PageRoute path="/reports" component={Reports} worksInNarrow={false} />
-
-      <PageRoute
-        path="/budget"
-        component={isNarrowWidth ? MobileBudget : Budget}
-      />
-
-      <NonPageRoute
-        path="/schedules"
-        exact
-        component={Schedules}
-        worksInNarrow={false}
-      />
-      <NonPageRoute
-        path="/schedule/edit"
-        exact
-        component={EditSchedule}
-        worksInNarrow={false}
-      />
-      <NonPageRoute
-        path="/schedule/edit/:id"
-        component={EditSchedule}
-        worksInNarrow={false}
-      />
-      <NonPageRoute
-        path="/schedule/link"
-        component={LinkSchedule}
-        worksInNarrow={false}
-      />
-      <NonPageRoute
-        path="/schedule/discover"
-        component={DiscoverSchedules}
-        worksInNarrow={false}
-      />
-      <NonPageRoute
-        path="/schedule/posts-offline-notification"
-        component={PostsOfflineNotification}
-      />
-
-      <NonPageRoute path="/payees" exact component={ManagePayeesPage} />
-      <NonPageRoute path="/rules" exact component={ManageRulesPage} />
-      <NonPageRoute path="/settings" component={Settings} />
-      <NonPageRoute
-        path="/nordigen/link"
-        exact
-        component={NordigenLink}
-        worksInNarrow={false}
-      />
-
-      <NonPageRoute
-        path="/accounts/:id"
-        exact
-        children={props => {
+      <Route path="/" exact render={() => <Redirect to="/budget" />} />
+
+      <Route path="/reports">
+        <NarrowNotSupported>
+          <Reports />
+        </NarrowNotSupported>
+      </Route>
+
+      <Route path="/budget">
+        {isNarrowWidth ? <MobileBudget /> : <Budget />}
+      </Route>
+
+      <Route path="/schedules" exact>
+        <NarrowNotSupported>
+          <Schedules />
+        </NarrowNotSupported>
+      </Route>
+      <Route path="/schedule/edit" exact>
+        <NarrowNotSupported>
+          <EditSchedule />
+        </NarrowNotSupported>
+      </Route>
+      <Route path="/schedule/edit/:id">
+        <NarrowNotSupported>
+          <EditSchedule />
+        </NarrowNotSupported>
+      </Route>
+      <Route path="/schedule/link">
+        <NarrowNotSupported>
+          <LinkSchedule />
+        </NarrowNotSupported>
+      </Route>
+      <Route path="/schedule/discover">
+        <NarrowNotSupported>
+          <DiscoverSchedules />
+        </NarrowNotSupported>
+      </Route>
+      <Route path="/schedule/posts-offline-notification">
+        <PostsOfflineNotification />
+      </Route>
+
+      <Route path="/payees" exact>
+        <ManagePayeesPage />
+      </Route>
+      <Route path="/rules" exact>
+        <ManageRulesPage />
+      </Route>
+      <Route path="/settings">
+        <Settings />
+      </Route>
+      <Route path="/nordigen/link" exact>
+        <NarrowNotSupported>
+          <NordigenLink />
+        </NarrowNotSupported>
+      </Route>
+
+      <Route path="/accounts/:id" exact>
+        {props => {
           const AcctCmp = isNarrowWidth ? MobileAccount : Account;
           return (
             props.match && <AcctCmp key={props.match.params.id} {...props} />
           );
         }}
-      />
-      <NonPageRoute
-        path="/accounts"
-        exact
-        component={isNarrowWidth ? MobileAccounts : Account}
-      />
+      </Route>
+      <Route path="/accounts" exact>
+        {isNarrowWidth ? <MobileAccounts /> : <Account />}
+      </Route>
     </Switch>
   );
 }
@@ -327,13 +291,10 @@ function FinancesApp(props) {
           <View style={{ flexDirection: 'row', flex: 1 }}>
             <FloatableSidebar />
 
-            <div
+            <View
               style={{
                 flex: 1,
-                display: 'flex',
-                flexDirection: 'column',
                 overflow: 'hidden',
-                position: 'relative',
                 width: '100%',
               }}
             >
@@ -362,11 +323,17 @@ function FinancesApp(props) {
               </div>
 
               <Switch>
-                <Route path="/budget" component={MobileNavTabs} />
-                <Route path="/accounts" component={MobileNavTabs} />
-                <Route path="/settings" component={MobileNavTabs} />
+                <Route path="/budget">
+                  <MobileNavTabs />
+                </Route>
+                <Route path="/accounts">
+                  <MobileNavTabs />
+                </Route>
+                <Route path="/settings">
+                  <MobileNavTabs />
+                </Route>
               </Switch>
-            </div>
+            </View>
           </View>
         </View>
       </CompatRouter>
diff --git a/packages/desktop-client/src/components/Modals.js b/packages/desktop-client/src/components/Modals.js
index 46df9f5b2..c18eeb859 100644
--- a/packages/desktop-client/src/components/Modals.js
+++ b/packages/desktop-client/src/components/Modals.js
@@ -112,164 +112,110 @@ function Modals({
           />
         </Route>
 
-        <Route
-          path="/confirm-category-delete"
-          render={() => {
-            const { category, group, onDelete } = options;
-            return (
-              <ConfirmCategoryDelete
-                modalProps={modalProps}
-                actions={actions}
-                category={categories.find(c => c.id === category)}
-                group={categoryGroups.find(g => g.id === group)}
-                categoryGroups={categoryGroups}
-                onDelete={onDelete}
-              />
-            );
-          }}
-        />
+        <Route path="/confirm-category-delete">
+          <ConfirmCategoryDelete
+            modalProps={modalProps}
+            actions={actions}
+            category={categories.find(c => c.id === options.category)}
+            group={categoryGroups.find(g => g.id === options.group)}
+            categoryGroups={categoryGroups}
+            onDelete={options.onDelete}
+          />
+        </Route>
 
-        <Route
-          path="/load-backup"
-          render={() => (
-            <LoadBackup
-              watchUpdates
-              budgetId={budgetId}
-              modalProps={modalProps}
-              actions={actions}
-            />
-          )}
-        />
+        <Route path="/load-backup">
+          <LoadBackup
+            watchUpdates
+            budgetId={budgetId}
+            modalProps={modalProps}
+            actions={actions}
+          />
+        </Route>
 
-        <Route
-          path="/manage-rules"
-          render={() => {
-            return (
-              <ManageRulesModal
-                history={history}
-                modalProps={modalProps}
-                payeeId={options.payeeId}
-              />
-            );
-          }}
-        />
+        <Route path="/manage-rules">
+          <ManageRulesModal
+            history={history}
+            modalProps={modalProps}
+            payeeId={options.payeeId}
+          />
+        </Route>
 
-        <Route
-          path="/edit-rule"
-          render={() => {
-            return (
-              <EditRule
-                history={history}
-                modalProps={modalProps}
-                defaultRule={options.rule}
-                onSave={options.onSave}
-              />
-            );
-          }}
-        />
+        <Route path="/edit-rule">
+          <EditRule
+            history={history}
+            modalProps={modalProps}
+            defaultRule={options.rule}
+            onSave={options.onSave}
+          />
+        </Route>
 
-        <Route
-          path="/merge-unused-payees"
-          render={() => {
-            return (
-              <MergeUnusedPayees
-                history={history}
-                modalProps={modalProps}
-                payeeIds={options.payeeIds}
-                targetPayeeId={options.targetPayeeId}
-              />
-            );
-          }}
-        />
+        <Route path="/merge-unused-payees">
+          <MergeUnusedPayees
+            history={history}
+            modalProps={modalProps}
+            payeeIds={options.payeeIds}
+            targetPayeeId={options.targetPayeeId}
+          />
+        </Route>
 
-        <Route
-          path="/plaid-external-msg"
-          render={() => {
-            return (
-              <PlaidExternalMsg
-                modalProps={modalProps}
-                actions={actions}
-                onMoveExternal={options.onMoveExternal}
-                onClose={() => {
-                  options.onClose && options.onClose();
-                  send('poll-web-token-stop');
-                }}
-                onSuccess={options.onSuccess}
-              />
-            );
-          }}
-        />
-        <Route
-          path="/nordigen-init"
-          render={() => {
-            return (
-              <NordigenInitialise
-                modalProps={modalProps}
-                onSuccess={options.onSuccess}
-              />
-            );
-          }}
-        />
-        <Route
-          path="/nordigen-external-msg"
-          render={() => {
-            return (
-              <NordigenExternalMsg
-                modalProps={modalProps}
-                actions={actions}
-                onMoveExternal={options.onMoveExternal}
-                onClose={() => {
-                  options.onClose && options.onClose();
-                  send('nordigen-poll-web-token-stop');
-                }}
-                onSuccess={options.onSuccess}
-              />
-            );
-          }}
-        />
+        <Route path="/plaid-external-msg">
+          <PlaidExternalMsg
+            modalProps={modalProps}
+            actions={actions}
+            onMoveExternal={options.onMoveExternal}
+            onClose={() => {
+              options.onClose && options.onClose();
+              send('poll-web-token-stop');
+            }}
+            onSuccess={options.onSuccess}
+          />
+        </Route>
+        <Route path="/nordigen-init">
+          <NordigenInitialise
+            modalProps={modalProps}
+            onSuccess={options.onSuccess}
+          />
+        </Route>
+        <Route path="/nordigen-external-msg">
+          <NordigenExternalMsg
+            modalProps={modalProps}
+            actions={actions}
+            onMoveExternal={options.onMoveExternal}
+            onClose={() => {
+              options.onClose && options.onClose();
+              send('nordigen-poll-web-token-stop');
+            }}
+            onSuccess={options.onSuccess}
+          />
+        </Route>
 
-        <Route
-          path="/create-encryption-key"
-          render={() => {
-            return (
-              <CreateEncryptionKey
-                key={name}
-                modalProps={modalProps}
-                actions={actions}
-                options={options}
-              />
-            );
-          }}
-        />
+        <Route path="/create-encryption-key">
+          <CreateEncryptionKey
+            key={name}
+            modalProps={modalProps}
+            actions={actions}
+            options={options}
+          />
+        </Route>
 
-        <Route
-          path="/fix-encryption-key"
-          render={() => {
-            return (
-              <FixEncryptionKey
-                key={name}
-                modalProps={modalProps}
-                actions={actions}
-                options={options}
-              />
-            );
-          }}
-        />
+        <Route path="/fix-encryption-key">
+          <FixEncryptionKey
+            key={name}
+            modalProps={modalProps}
+            actions={actions}
+            options={options}
+          />
+        </Route>
 
-        <Route
-          path="/edit-field"
-          render={() => {
-            return (
-              <EditField
-                key={name}
-                modalProps={modalProps}
-                actions={actions}
-                name={options.name}
-                onSubmit={options.onSubmit}
-              />
-            );
-          }}
-        />
+        <Route path="/edit-field">
+          <EditField
+            key={name}
+            modalProps={modalProps}
+            actions={actions}
+            name={options.name}
+            onSubmit={options.onSubmit}
+          />
+        </Route>
 
         <Route path="/budget-summary">
           <BudgetSummary
diff --git a/packages/desktop-client/src/components/Titlebar.js b/packages/desktop-client/src/components/Titlebar.js
index 1b80258ad..407e4c641 100644
--- a/packages/desktop-client/src/components/Titlebar.js
+++ b/packages/desktop-client/src/components/Titlebar.js
@@ -6,7 +6,7 @@ import React, {
   useContext,
 } from 'react';
 import { connect } from 'react-redux';
-import { Switch, Route, withRouter } from 'react-router-dom';
+import { Switch, Route, useLocation, useHistory } from 'react-router-dom';
 
 import { css, media } from 'glamor';
 
@@ -258,7 +258,6 @@ function BudgetTitlebar({ globalPrefs, saveGlobalPrefs, localPrefs }) {
 }
 
 function Titlebar({
-  location,
   globalPrefs,
   saveGlobalPrefs,
   localPrefs,
@@ -269,6 +268,8 @@ function Titlebar({
   style,
   sync,
 }) {
+  let history = useHistory();
+  let location = useLocation();
   let sidebar = useSidebar();
   let { isNarrowWidth } = useResponsive();
   const serverURL = useServerURL();
@@ -320,45 +321,30 @@ function Titlebar({
       )}
 
       <Switch>
-        <Route
-          path="/accounts"
-          exact
-          children={props => {
-            let state = props.location.state || {};
-            return state.goBack ? (
-              <Button onClick={() => props.history.goBack()} bare>
-                <ArrowLeft
-                  width={10}
-                  height={10}
-                  style={{ marginRight: 5, color: 'currentColor' }}
-                />{' '}
-                Back
-              </Button>
-            ) : null;
-          }}
-        />
+        <Route path="/accounts" exact>
+          {location.state?.goBack ? (
+            <Button onClick={() => history.goBack()} bare>
+              <ArrowLeft
+                width={10}
+                height={10}
+                style={{ marginRight: 5, color: 'currentColor' }}
+              />{' '}
+              Back
+            </Button>
+          ) : null}
+        </Route>
 
-        <Route
-          path="/accounts/:id"
-          exact
-          children={props => {
-            return (
-              props.match && <AccountSyncCheck id={props.match.params.id} />
-            );
-          }}
-        />
+        <Route path="/accounts/:id" exact>
+          <AccountSyncCheck />
+        </Route>
 
-        <Route
-          path="/budget"
-          exact
-          children={() => (
-            <BudgetTitlebar
-              globalPrefs={globalPrefs}
-              saveGlobalPrefs={saveGlobalPrefs}
-              localPrefs={localPrefs}
-            />
-          )}
-        />
+        <Route path="/budget" exact>
+          <BudgetTitlebar
+            globalPrefs={globalPrefs}
+            saveGlobalPrefs={saveGlobalPrefs}
+            localPrefs={localPrefs}
+          />
+        </Route>
       </Switch>
       <View style={{ flex: 1 }} />
       <UncategorizedButton />
@@ -374,14 +360,12 @@ function Titlebar({
   );
 }
 
-export default withRouter(
-  connect(
-    state => ({
-      globalPrefs: state.prefs.global,
-      localPrefs: state.prefs.local,
-      userData: state.user.data,
-      floatingSidebar: state.prefs.global.floatingSidebar,
-    }),
-    actions,
-  )(Titlebar),
-);
+export default connect(
+  state => ({
+    globalPrefs: state.prefs.global,
+    localPrefs: state.prefs.local,
+    userData: state.user.data,
+    floatingSidebar: state.prefs.global.floatingSidebar,
+  }),
+  actions,
+)(Titlebar);
diff --git a/packages/desktop-client/src/components/accounts/Account.js b/packages/desktop-client/src/components/accounts/Account.js
index 7d7ae712c..921799996 100644
--- a/packages/desktop-client/src/components/accounts/Account.js
+++ b/packages/desktop-client/src/components/accounts/Account.js
@@ -2001,6 +2001,7 @@ class AccountInternal extends PureComponent {
 
 function AccountHack(props) {
   let { dispatch: splitsExpandedDispatch } = useSplitsExpanded();
+
   return (
     <AccountInternal
       {...props}
@@ -2009,8 +2010,12 @@ function AccountHack(props) {
   );
 }
 
-export default function Account(props) {
+export default function Account() {
   const syncEnabled = useFeatureFlag('syncAccount');
+  let params = useParams();
+  let location = useLocation();
+  let activeLocation = useActiveLocation();
+
   let state = useSelector(state => ({
     newTransactions: state.queries.newTransactions,
     matchedTransactions: state.queries.matchedTransactions,
@@ -2019,16 +2024,11 @@ export default function Account(props) {
     categoryGroups: state.queries.categories.grouped,
     dateFormat: state.prefs.local.dateFormat || 'MM/dd/yyyy',
     hideFraction: state.prefs.local.hideFraction || false,
-    expandSplits: props.match && state.prefs.local['expand-splits'],
-    showBalances:
-      props.match &&
-      state.prefs.local['show-balances-' + props.match.params.id],
-    showCleared:
-      props.match &&
-      !state.prefs.local['hide-cleared-' + props.match.params.id],
+    expandSplits: state.prefs.local['expand-splits'],
+    showBalances: params.id && state.prefs.local['show-balances-' + params.id],
+    showCleared: params.id && !state.prefs.local['hide-cleared-' + params.id],
     showExtraBalances:
-      props.match &&
-      state.prefs.local['show-extra-balances-' + props.match.params.id],
+      params.id && state.prefs.local['show-extra-balances-' + params.id],
     payees: state.queries.payees,
     modalShowing: state.modals.modalStack.length > 0,
     accountsSyncing: state.account.accountsSyncing,
@@ -2042,10 +2042,6 @@ export default function Account(props) {
     [dispatch],
   );
 
-  let params = useParams();
-  let location = useLocation();
-  let activeLocation = useActiveLocation();
-
   let transform = useMemo(() => {
     let filterByAccount = queries.getAccountFilter(params.id, '_account');
     let filterByPayee = queries.getAccountFilter(
@@ -2085,7 +2081,7 @@ export default function Account(props) {
             !!(activeLocation.state && activeLocation.state.locationPtr)
           }
           accountId={params.id}
-          location={props.location}
+          location={location}
         />
       </SplitsExpandedProvider>
     </SchedulesProvider>
diff --git a/packages/desktop-client/src/components/accounts/MobileAccount.js b/packages/desktop-client/src/components/accounts/MobileAccount.js
index cefcc54d5..2db1f2ca3 100644
--- a/packages/desktop-client/src/components/accounts/MobileAccount.js
+++ b/packages/desktop-client/src/components/accounts/MobileAccount.js
@@ -1,5 +1,6 @@
 import React, { useEffect, useMemo, useState } from 'react';
 import { connect, useDispatch, useSelector } from 'react-redux';
+import { useParams } from 'react-router-dom';
 import { useNavigate } from 'react-router-dom-v5-compat';
 
 import debounce from 'debounce';
@@ -88,12 +89,9 @@ function Account(props) {
     [dispatch],
   );
 
-  const { id: accountId } = props.match.params;
+  const { id: accountId } = useParams();
 
-  const makeRootQuery = () => {
-    const { id } = props.match.params || {};
-    return queries.makeTransactionsQuery(id);
-  };
+  const makeRootQuery = () => queries.makeTransactionsQuery(accountId);
 
   const updateQuery = query => {
     if (paged) {
diff --git a/packages/desktop-client/src/components/manager/ManagementApp.js b/packages/desktop-client/src/components/manager/ManagementApp.js
index d5724e0da..7c90c2514 100644
--- a/packages/desktop-client/src/components/manager/ManagementApp.js
+++ b/packages/desktop-client/src/components/manager/ManagementApp.js
@@ -151,16 +151,20 @@ function ManagementApp({
             {userData && files ? (
               <>
                 <Switch>
-                  <Route exact path="/config-server" component={ConfigServer} />
-                  <Route
-                    exact
-                    path="/change-password"
-                    component={ChangePassword}
-                  />
+                  <Route exact path="/config-server">
+                    <ConfigServer />
+                  </Route>
+                  <Route exact path="/change-password">
+                    <ChangePassword />
+                  </Route>
                   {files && files.length > 0 ? (
-                    <Route exact path="/" component={BudgetList} />
+                    <Route exact path="/">
+                      <BudgetList />
+                    </Route>
                   ) : (
-                    <Route exact path="/" component={WelcomeScreen} />
+                    <Route exact path="/">
+                      <WelcomeScreen />
+                    </Route>
                   )}
                   {/* Redirect all other pages to this route */}
                   <Route path="/" render={() => <Redirect to="/" />} />
@@ -176,23 +180,27 @@ function ManagementApp({
                   }}
                 >
                   <Switch>
-                    <Route exact path="/config-server" component={null} />
-                    <Route
-                      exact
-                      path="/"
-                      render={() => (
-                        <LoggedInUser style={{ padding: '4px 7px' }} />
-                      )}
-                    />
+                    <Route exact path="/config-server" children={null} />
+                    <Route exact path="/">
+                      <LoggedInUser style={{ padding: '4px 7px' }} />
+                    </Route>
                   </Switch>
                 </View>
               </>
             ) : (
               <Switch>
-                <Route exact path="/login" component={Login} />
-                <Route exact path="/error" component={Error} />
-                <Route exact path="/config-server" component={ConfigServer} />
-                <Route exact path="/bootstrap" component={Bootstrap} />
+                <Route exact path="/login">
+                  <Login />
+                </Route>
+                <Route exact path="/error">
+                  <Error />
+                </Route>
+                <Route exact path="/config-server">
+                  <ConfigServer />
+                </Route>
+                <Route exact path="/bootstrap">
+                  <Bootstrap />
+                </Route>
                 {/* Redirect all other pages to this route */}
                 <Route path="/" render={() => <Redirect to="/bootstrap" />} />
               </Switch>
@@ -201,8 +209,10 @@ function ManagementApp({
         )}
 
         <Switch>
-          <Route exact path="/config-server" component={null} />
-          <Route path="/" component={ServerURL} />
+          <Route exact path="/config-server" children={null} />
+          <Route path="/">
+            <ServerURL />
+          </Route>
         </Switch>
         <Version />
       </View>
diff --git a/packages/desktop-client/src/components/modals/ManageRulesModal.js b/packages/desktop-client/src/components/modals/ManageRulesModal.js
index 759585454..1eb05415a 100644
--- a/packages/desktop-client/src/components/modals/ManageRulesModal.js
+++ b/packages/desktop-client/src/components/modals/ManageRulesModal.js
@@ -1,5 +1,5 @@
 import React, { useState } from 'react';
-import { useLocation } from 'react-router-dom-v5-compat';
+import { useLocation } from 'react-router-dom';
 
 import { isNonProductionEnvironment } from 'loot-core/src/shared/environment';
 
diff --git a/packages/desktop-client/src/components/reports/index.js b/packages/desktop-client/src/components/reports/index.js
index 08ef98347..75af78499 100644
--- a/packages/desktop-client/src/components/reports/index.js
+++ b/packages/desktop-client/src/components/reports/index.js
@@ -10,9 +10,15 @@ import Overview from './Overview';
 export default function Reports() {
   return (
     <View style={{ flex: 1 }} data-testid="reports-page">
-      <Route path="/reports" exact component={Overview} />
-      <Route path="/reports/net-worth" exact component={NetWorth} />
-      <Route path="/reports/cash-flow" exact component={CashFlow} />
+      <Route path="/reports" exact>
+        <Overview />
+      </Route>
+      <Route path="/reports/net-worth" exact>
+        <NetWorth />
+      </Route>
+      <Route path="/reports/cash-flow" exact>
+        <CashFlow />
+      </Route>
     </View>
   );
 }
diff --git a/upcoming-release-notes/1045.md b/upcoming-release-notes/1045.md
new file mode 100644
index 000000000..f31fafc1b
--- /dev/null
+++ b/upcoming-release-notes/1045.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [trevdor]
+---
+
+Update to React Router v5.1 conventions to facilitate the v6 upgrade.
-- 
GitLab