Repository: joinmarket-webui/jam
Pull request #519 (2022-09-26 13:56:41)

deps: update `react-router-dom` from v6.3.0 to v6.4.1
Updates dependency `react-router-dom` from v6.3.0 to v6.4.1.

Originally wanted to leverage the [new `loader` feature](https://reactrouter.com/en/main/route/loader#loader) to separate data loading from view rendering.
This will be done in a follow-up PR as we often update context data which cannot be done in a satisfactory way yet (see https://github.com/remix-run/react-router/issues/9324).


Patch:
diff --git a/package-lock.json b/package-lock.json
index 4e02bf8..70870ce 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -42,7 +42,7 @@
         "react-dom": "^17.0.2",
         "react-i18next": "^11.18.6",
         "react-router-bootstrap": "^0.26.2",
-        "react-router-dom": "^6.3.0",
+        "react-router-dom": "^6.4.1",
         "react-scripts": "^5.0.1",
         "typescript": "^4.7.2"
       },
@@ -3833,9 +3833,9 @@
       }
     },
     "node_modules/@remix-run/router": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.0.tgz",
-      "integrity": "sha512-SCR1cxRSMNKjaVYptCzBApPDqGwa3FGdjVHc+rOToocNPHQdIYLZBfv/3f+KvYuXDkUGVIW9IAzmPNZDRL1I4A==",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.1.tgz",
+      "integrity": "sha512-eBV5rvW4dRFOU1eajN7FmYxjAIVz/mRHgUE9En9mBn6m3mulK3WTR5C3iQhL9MZ14rWAq+xOlEaCkDiW0/heOg==",
       "dev": true,
       "engines": {
         "node": ">=14"
@@ -18613,12 +18613,12 @@
       }
     },
     "node_modules/react-router": {
-      "version": "6.4.0",
-      "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.0.tgz",
-      "integrity": "sha512-B+5bEXFlgR1XUdHYR6P94g299SjrfCBMmEDJNcFbpAyRH1j1748yt9NdDhW3++nw1lk3zQJ6aOO66zUx3KlTZg==",
+      "version": "6.4.1",
+      "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.1.tgz",
+      "integrity": "sha512-OJASKp5AykDWFewgWUim1vlLr7yfD4vO/h+bSgcP/ix8Md+LMHuAjovA74MQfsfhQJGGN1nHRhwS5qQQbbBt3A==",
       "dev": true,
       "dependencies": {
-        "@remix-run/router": "1.0.0"
+        "@remix-run/router": "1.0.1"
       },
       "engines": {
         "node": ">=14"
@@ -18641,12 +18641,13 @@
       }
     },
     "node_modules/react-router-dom": {
-      "version": "6.4.0",
-      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.0.tgz",
-      "integrity": "sha512-4Aw1xmXKeleYYQ3x0Lcl2undHR6yMjXZjd9DKZd53SGOYqirrUThyUb0wwAX5VZAyvSuzjNJmZlJ3rR9+/vzqg==",
+      "version": "6.4.1",
+      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.1.tgz",
+      "integrity": "sha512-MY7NJCrGNVJtGp8ODMOBHu20UaIkmwD2V3YsAOUQoCXFk7Ppdwf55RdcGyrSj+ycSL9Uiwrb3gTLYSnzcRoXww==",
       "dev": true,
       "dependencies": {
-        "react-router": "6.4.0"
+        "@remix-run/router": "1.0.1",
+        "react-router": "6.4.1"
       },
       "engines": {
         "node": ">=14"
@@ -25477,9 +25478,9 @@
       }
     },
     "@remix-run/router": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.0.tgz",
-      "integrity": "sha512-SCR1cxRSMNKjaVYptCzBApPDqGwa3FGdjVHc+rOToocNPHQdIYLZBfv/3f+KvYuXDkUGVIW9IAzmPNZDRL1I4A==",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.1.tgz",
+      "integrity": "sha512-eBV5rvW4dRFOU1eajN7FmYxjAIVz/mRHgUE9En9mBn6m3mulK3WTR5C3iQhL9MZ14rWAq+xOlEaCkDiW0/heOg==",
       "dev": true
     },
     "@restart/hooks": {
@@ -36340,12 +36341,12 @@
       "dev": true
     },
     "react-router": {
-      "version": "6.4.0",
-      "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.0.tgz",
-      "integrity": "sha512-B+5bEXFlgR1XUdHYR6P94g299SjrfCBMmEDJNcFbpAyRH1j1748yt9NdDhW3++nw1lk3zQJ6aOO66zUx3KlTZg==",
+      "version": "6.4.1",
+      "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.1.tgz",
+      "integrity": "sha512-OJASKp5AykDWFewgWUim1vlLr7yfD4vO/h+bSgcP/ix8Md+LMHuAjovA74MQfsfhQJGGN1nHRhwS5qQQbbBt3A==",
       "dev": true,
       "requires": {
-        "@remix-run/router": "1.0.0"
+        "@remix-run/router": "1.0.1"
       }
     },
     "react-router-bootstrap": {
@@ -36358,12 +36359,13 @@
       }
     },
     "react-router-dom": {
-      "version": "6.4.0",
-      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.0.tgz",
-      "integrity": "sha512-4Aw1xmXKeleYYQ3x0Lcl2undHR6yMjXZjd9DKZd53SGOYqirrUThyUb0wwAX5VZAyvSuzjNJmZlJ3rR9+/vzqg==",
+      "version": "6.4.1",
+      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.1.tgz",
+      "integrity": "sha512-MY7NJCrGNVJtGp8ODMOBHu20UaIkmwD2V3YsAOUQoCXFk7Ppdwf55RdcGyrSj+ycSL9Uiwrb3gTLYSnzcRoXww==",
       "dev": true,
       "requires": {
-        "react-router": "6.4.0"
+        "@remix-run/router": "1.0.1",
+        "react-router": "6.4.1"
       }
     },
     "react-scripts": {
diff --git a/package.json b/package.json
index d72efbe..e76c4f7 100644
--- a/package.json
+++ b/package.json
@@ -40,7 +40,7 @@
     "react-dom": "^17.0.2",
     "react-i18next": "^11.18.6",
     "react-router-bootstrap": "^0.26.2",
-    "react-router-dom": "^6.3.0",
+    "react-router-dom": "^6.4.1",
     "react-scripts": "^5.0.1",
     "typescript": "^4.7.2"
   },
diff --git a/src/components/App.tsx b/src/components/App.tsx
index 7ea0c05..d3d98e5 100644
--- a/src/components/App.tsx
+++ b/src/components/App.tsx
@@ -1,7 +1,7 @@
 import { useCallback } from 'react'
 import * as rb from 'react-bootstrap'
 import { useTranslation } from 'react-i18next'
-import { Navigate, Route, Routes } from 'react-router-dom'
+import { createBrowserRouter, createRoutesFromElements, Navigate, Route, RouterProvider } from 'react-router-dom'
 import { routes } from '../constants/routes'
 import { useSessionConnectionError } from '../context/ServiceInfoContext'
 import { useSettings } from '../context/SettingsContext'
@@ -40,6 +40,62 @@ export default function App() {
     setCurrentWallet(null)
   }, [setCurrentWallet])
 
+  const router = createBrowserRouter(
+    createRoutesFromElements(
+      <Route
+        id="base"
+        element={
+          <>
+            <Navbar />
+            <rb.Container as="main" className="py-4 py-sm-5">
+              {sessionConnectionError && (
+                <rb.Alert variant="danger">
+                  {t('app.alert_no_connection', { connectionError: sessionConnectionError.message })}.
+                </rb.Alert>
+              )}
+
+              <Layout />
+            </rb.Container>
+            <Footer />
+          </>
+        }
+      >
+        {/**
+         * This sections defines all routes that can be displayed, even if the connection
+         * to the backend is down, e.g. "create-wallet" shows the seed quiz and it is important
+         * that it stays visible in case the backend becomes unavailable.
+         */}
+        <Route id="create-wallet" path={routes.createWallet} element={<CreateWallet startWallet={startWallet} />} />
+        {/**
+         * This section defines all routes that are displayed only if the backend is reachable.
+         */}
+        {!sessionConnectionError && (
+          <>
+            <Route
+              id="wallets"
+              path={routes.home}
+              element={<Wallets currentWallet={currentWallet} startWallet={startWallet} stopWallet={stopWallet} />}
+            />
+            {currentWallet && (
+              <>
+                <Route id="wallet" path={routes.wallet} element={<MainWalletView />} />
+                <Route id="jam" path={routes.jam} element={<Jam />} />
+                <Route id="send" path={routes.send} element={<Send />} />
+                <Route id="earn" path={routes.earn} element={<Earn />} />
+                <Route id="receive" path={routes.receive} element={<Receive />} />
+                <Route id="settings" path={routes.settings} element={<Settings stopWallet={stopWallet} />} />
+              </>
+            )}
+            <Route id="404" path="*" element={<Navigate to={routes.home} replace={true} />} />
+          </>
+        )}
+      </Route>
+    ),
+    {
+      basename: window.JM.PUBLIC_PATH,
+    }
+  )
+
   if (settings.showOnboarding === true) {
     return (
       <rb.Container className="onboarding my-5">
@@ -52,51 +108,5 @@ export default function App() {
     )
   }
 
-  return (
-    <>
-      <Navbar />
-      <rb.Container as="main" className="py-4 py-sm-5">
-        {sessionConnectionError && (
-          <rb.Alert variant="danger">
-            {t('app.alert_no_connection', { connectionError: sessionConnectionError.message })}.
-          </rb.Alert>
-        )}
-        <Routes>
-          {/**
-           * This sections defines all routes that can be displayed, even if the connection
-           * to the backend is down, e.g. "create-wallet" shows the seed quiz and it is important
-           * that it stays visible in case the backend becomes unavailable.
-           */}
-          <Route element={<Layout />}>
-            <Route path={routes.createWallet} element={<CreateWallet startWallet={startWallet} />} />
-          </Route>
-          {/**
-           * This section defines all routes that are displayed only if the backend is reachable.
-           */}
-          {!sessionConnectionError && (
-            <>
-              <Route element={<Layout />}>
-                <Route
-                  path={routes.home}
-                  element={<Wallets currentWallet={currentWallet} startWallet={startWallet} stopWallet={stopWallet} />}
-                />
-                {currentWallet && (
-                  <>
-                    <Route path={routes.wallet} element={<MainWalletView />} />
-                    <Route path={routes.jam} element={<Jam />} />
-                    <Route path={routes.send} element={<Send />} />
-                    <Route path={routes.earn} element={<Earn />} />
-                    <Route path={routes.receive} element={<Receive />} />
-                    <Route path={routes.settings} element={<Settings stopWallet={stopWallet} />} />
-                  </>
-                )}
-              </Route>
-              <Route path="*" element={<Navigate to={routes.home} replace={true} />} />
-            </>
-          )}
-        </Routes>
-      </rb.Container>
-      <Footer />
-    </>
-  )
+  return <RouterProvider router={router} />
 }
diff --git a/src/components/MainWalletView.jsx b/src/components/MainWalletView.jsx
index 905fef8..750c3ee 100644
--- a/src/components/MainWalletView.jsx
+++ b/src/components/MainWalletView.jsx
@@ -1,17 +1,17 @@
-import React, { useEffect, useState, useMemo } from 'react'
+import { useEffect, useState, useMemo } from 'react'
 import * as rb from 'react-bootstrap'
 import { useTranslation } from 'react-i18next'
 import { useNavigate } from 'react-router-dom'
 import { useSettings, useSettingsDispatch } from '../context/SettingsContext'
 import { useCurrentWallet, useCurrentWalletInfo, useReloadCurrentWalletInfo } from '../context/WalletContext'
+import { walletDisplayName } from '../utils'
+import { routes } from '../constants/routes'
 import Balance from './Balance'
 import Sprite from './Sprite'
-import { walletDisplayName } from '../utils'
-import styles from './MainWalletView.module.css'
 import { ExtendedLink } from './ExtendedLink'
-import { routes } from '../constants/routes'
 import { JarDetailsOverlay } from './jar_details/JarDetailsOverlay'
 import { Jars } from './Jars'
+import styles from './MainWalletView.module.css'
 
 const WalletHeader = ({ name, balance, unit, showBalance, loading }) => {
   return (
diff --git a/src/components/Receive.jsx b/src/components/Receive.jsx
index baa8b1c..8af0057 100644
--- a/src/components/Receive.jsx
+++ b/src/components/Receive.jsx
@@ -1,8 +1,7 @@
-import React, { useState, useEffect, useMemo } from 'react'
-import { useLocation } from 'react-router-dom'
+import { useState, useEffect, useMemo } from 'react'
 import * as rb from 'react-bootstrap'
 import { useTranslation } from 'react-i18next'
-
+import { useLocation } from 'react-router-dom'
 import { useSettings } from '../context/SettingsContext'
 import { useCurrentWallet, useCurrentWalletInfo } from '../context/WalletContext'
 import * as Api from '../libs/JmWalletApi'
diff --git a/src/index.tsx b/src/index.tsx
index 3c06f86..187cd6d 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,6 +1,5 @@
 import React from 'react'
 import ReactDOM from 'react-dom'
-import { BrowserRouter } from 'react-router-dom'
 // @ts-ignore
 import App from './components/App'
 // @ts-ignore
@@ -17,19 +16,17 @@ import './i18n/config'
 
 ReactDOM.render(
   <React.StrictMode>
-    <BrowserRouter basename={window.JM.PUBLIC_PATH}>
-      <SettingsProvider>
-        <WalletProvider>
-          <ServiceConfigProvider>
-            <WebsocketProvider>
-              <ServiceInfoProvider>
-                <App />
-              </ServiceInfoProvider>
-            </WebsocketProvider>
-          </ServiceConfigProvider>
-        </WalletProvider>
-      </SettingsProvider>
-    </BrowserRouter>
+    <SettingsProvider>
+      <WalletProvider>
+        <ServiceConfigProvider>
+          <WebsocketProvider>
+            <ServiceInfoProvider>
+              <App />
+            </ServiceInfoProvider>
+          </WebsocketProvider>
+        </ServiceConfigProvider>
+      </WalletProvider>
+    </SettingsProvider>
   </React.StrictMode>,
   document.getElementById('root')
 )


Test patch:
diff --git a/src/components/CreateWallet.test.jsx b/src/components/CreateWallet.test.jsx
index df3b8be..c8daa64 100644
--- a/src/components/CreateWallet.test.jsx
+++ b/src/components/CreateWallet.test.jsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import { BrowserRouter } from 'react-router-dom'
 import user from '@testing-library/user-event'
 import { render, screen, waitFor } from '../testUtils'
 import { act } from 'react-dom/test-utils'
@@ -22,7 +22,11 @@ describe('<CreateWallet />', () => {
 
   const setup = (props) => {
     const startWallet = props?.startWallet || NOOP
-    render(<CreateWallet startWallet={startWallet} />)
+    render(
+      <BrowserRouter>
+        <CreateWallet startWallet={startWallet} />
+      </BrowserRouter>
+    )
   }
 
   beforeEach(() => {
diff --git a/src/components/Settings.test.jsx b/src/components/Settings.test.jsx
index cc9b0a8..892fbdd 100644
--- a/src/components/Settings.test.jsx
+++ b/src/components/Settings.test.jsx
@@ -1,4 +1,5 @@
-import React from 'react'
+import { BrowserRouter } from 'react-router-dom'
+
 import { render, screen } from '../testUtils'
 import { act } from 'react-dom/test-utils'
 
@@ -6,7 +7,11 @@ import Settings from './Settings'
 
 describe('<Settings />', () => {
   const setup = () => {
-    render(<Settings />)
+    render(
+      <BrowserRouter>
+        <Settings />
+      </BrowserRouter>
+    )
   }
 
   it('should render settings without errors', () => {
diff --git a/src/components/Wallet.test.jsx b/src/components/Wallet.test.jsx
index edd2fba..c60d99e 100644
--- a/src/components/Wallet.test.jsx
+++ b/src/components/Wallet.test.jsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import { BrowserRouter } from 'react-router-dom'
 import { render, screen, waitFor } from '../testUtils'
 import { act } from 'react-dom/test-utils'
 import user from '@testing-library/user-event'
@@ -28,14 +28,16 @@ describe('<Wallet />', () => {
     coinjoinInProgress = false,
   }) => {
     render(
-      <Wallet
-        name={name}
-        lockWallet={lockWallet}
-        unlockWallet={unlockWallet}
-        isActive={isActive}
-        coinjoinInProgress={coinjoinInProgress}
-        makerRunning={makerRunning}
-      />
+      <BrowserRouter>
+        <Wallet
+          name={name}
+          lockWallet={lockWallet}
+          unlockWallet={unlockWallet}
+          isActive={isActive}
+          coinjoinInProgress={coinjoinInProgress}
+          makerRunning={makerRunning}
+        />
+      </BrowserRouter>
     )
   }
 
diff --git a/src/components/Wallets.test.jsx b/src/components/Wallets.test.jsx
index 7df4817..c991684 100644
--- a/src/components/Wallets.test.jsx
+++ b/src/components/Wallets.test.jsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import { BrowserRouter } from 'react-router-dom'
 import { render, screen, waitFor, waitForElementToBeRemoved } from '../testUtils'
 import { act } from 'react-dom/test-utils'
 import user from '@testing-library/user-event'
@@ -28,7 +28,11 @@ describe('<Wallets />', () => {
   const mockStopWallet = jest.fn()
 
   const setup = ({ currentWallet = null }) => {
-    render(<Wallets currentWallet={currentWallet} startWallet={mockStartWallet} stopWallet={mockStopWallet} />)
+    render(
+      <BrowserRouter>
+        <Wallets currentWallet={currentWallet} startWallet={mockStartWallet} stopWallet={mockStopWallet} />
+      </BrowserRouter>
+    )
   }
 
   beforeEach(() => {
diff --git a/src/testUtils.tsx b/src/testUtils.tsx
index 83823ab..5377a66 100644
--- a/src/testUtils.tsx
+++ b/src/testUtils.tsx
@@ -1,6 +1,5 @@
 import React from 'react'
 import { render, RenderOptions } from '@testing-library/react'
-import { BrowserRouter } from 'react-router-dom'
 import { I18nextProvider } from 'react-i18next'
 import { WalletProvider } from './context/WalletContext'
 import { ServiceInfoProvider } from './context/ServiceInfoContext'
@@ -14,19 +13,17 @@ import i18n from './i18n/testConfig'
 const AllTheProviders = ({ children }: { children: React.ReactElement }) => {
   return (
     <React.StrictMode>
-      <BrowserRouter>
-        <I18nextProvider i18n={i18n}>
-          <SettingsProvider>
-            <WalletProvider>
-              <ServiceConfigProvider>
-                <WebsocketProvider>
-                  <ServiceInfoProvider>{children}</ServiceInfoProvider>
-                </WebsocketProvider>
-              </ServiceConfigProvider>
-            </WalletProvider>
-          </SettingsProvider>
-        </I18nextProvider>
-      </BrowserRouter>
+      <I18nextProvider i18n={i18n}>
+        <SettingsProvider>
+          <WalletProvider>
+            <ServiceConfigProvider>
+              <WebsocketProvider>
+                <ServiceInfoProvider>{children}</ServiceInfoProvider>
+              </WebsocketProvider>
+            </ServiceConfigProvider>
+          </WalletProvider>
+        </SettingsProvider>
+      </I18nextProvider>
     </React.StrictMode>
   )
 }