From e97fe2e1f302f1d7ca477de3ed076bf694cda637 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 18:05:57 +0800 Subject: [PATCH] chore(deps): update dependency react-router-dom to v6.10.0 (#3238) * chore(deps): update dependency react-router-dom to v6.10.0 * fix: lockfile * fix: react router * chore: add annotations about the type definition file * fix: bump version number for ui package --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Charles Zhao --- packages/console/package.json | 2 +- .../UnsavedChangesAlertModal/index.tsx | 93 ++++--------------- .../src/include.d/react-router-dom.d.ts | 16 ++++ packages/console/src/pages/Main/index.tsx | 41 ++++---- packages/ui/package.json | 2 +- .../ui/src/include.d/react-router-dom.d.ts | 16 ++++ pnpm-lock.yaml | 50 ++++------ 7 files changed, 96 insertions(+), 124 deletions(-) create mode 100644 packages/console/src/include.d/react-router-dom.d.ts create mode 100644 packages/ui/src/include.d/react-router-dom.d.ts diff --git a/packages/console/package.json b/packages/console/package.json index 42ae87b0a..31deeba6c 100644 --- a/packages/console/package.json +++ b/packages/console/package.json @@ -93,7 +93,7 @@ "react-markdown": "^8.0.0", "react-modal": "^3.15.1", "react-paginate": "^8.1.3", - "react-router-dom": "6.3.0", + "react-router-dom": "^6.10.0", "react-syntax-highlighter": "^15.5.0", "react-timer-hook": "^3.0.5", "recharts": "^2.1.13", diff --git a/packages/console/src/components/UnsavedChangesAlertModal/index.tsx b/packages/console/src/components/UnsavedChangesAlertModal/index.tsx index 0bf33fd6e..36d7b6d13 100644 --- a/packages/console/src/components/UnsavedChangesAlertModal/index.tsx +++ b/packages/console/src/components/UnsavedChangesAlertModal/index.tsx @@ -1,97 +1,42 @@ -import type { Blocker, Transition } from 'history'; -import { useCallback, useContext, useLayoutEffect, useState } from 'react'; +import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; -import type { Navigator } from 'react-router-dom'; -import { UNSAFE_NavigationContext } from 'react-router-dom'; +import { unstable_useBlocker as useBlocker, useLocation } from 'react-router-dom'; import ConfirmModal from '../ConfirmModal'; -/** - * The `usePrompt` and `useBlock` hooks are removed from react-router v6, as the developers think - * they are not ready to be shipped in v6. Reference: https://github.com/remix-run/react-router/issues/8139 - * Therefore we have to implement our own workaround to provide the same functionality, through `UNSAFE_NavigationContext`. - */ -type BlockFunction = (blocker: Blocker) => () => void; - -type BlockerNavigator = Navigator & { - location: Location; - block: BlockFunction; -}; - type Props = { hasUnsavedChanges: boolean; parentPath?: string; }; function UnsavedChangesAlertModal({ hasUnsavedChanges, parentPath }: Props) { - const { navigator } = useContext(UNSAFE_NavigationContext); - - /** - * Props `block` and `location` are removed from `Navigator` type in react-router, for the same reason as above. - * So we have to define our own type `BlockerNavigator` to acquire these props that actually exist in `navigator` object. - */ - // eslint-disable-next-line no-restricted-syntax - const { block, location } = navigator as BlockerNavigator; - - const [displayAlert, setDisplayAlert] = useState(false); - const [transition, setTransition] = useState(); - const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); + const { pathname } = useLocation(); + const blocker = useBlocker(hasUnsavedChanges); - useLayoutEffect(() => { - if (!hasUnsavedChanges) { + // Reset the blocker if the conditions are met. + useEffect(() => { + if (blocker.state !== 'blocked') { return; } - const { pathname } = location; - - const unblock = block((transition) => { - const { - location: { pathname: targetPathname }, - } = transition; - - // Note: We don't want to show the alert if the user is navigating to the same page. - if (targetPathname === pathname) { - return; - } - - if (parentPath && targetPathname.startsWith(parentPath)) { - unblock(); - transition.retry(); - - return; - } - - setDisplayAlert(true); - - setTransition({ - ...transition, - retry() { - unblock(); - transition.retry(); - }, - }); - }); - - return unblock; - }, [navigator, hasUnsavedChanges, location, block, parentPath]); - - const leavePage = useCallback(() => { - transition?.retry(); - setDisplayAlert(false); - }, [transition]); - - const stayOnPage = useCallback(() => { - setDisplayAlert(false); - }, [setDisplayAlert]); + const targetPathname = blocker.location.pathname; + if (!hasUnsavedChanges || targetPathname === pathname) { + blocker.reset(); + return; + } + if (parentPath && targetPathname.startsWith(parentPath)) { + blocker.proceed(); + } + }, [blocker, pathname, hasUnsavedChanges, parentPath]); return ( {t('general.unsaved_changes_warning')} diff --git a/packages/console/src/include.d/react-router-dom.d.ts b/packages/console/src/include.d/react-router-dom.d.ts new file mode 100644 index 000000000..56d37327a --- /dev/null +++ b/packages/console/src/include.d/react-router-dom.d.ts @@ -0,0 +1,16 @@ +/** + * This type definition file is a workaround for the fact that react-router-dom + * declares location status type as `any` instead of `unknown`, which ends up + * causing issues with strict type narrowing in TypeScript. + * + * Reference: https://github.com/remix-run/react-router/issues/10241 + */ + +// eslint-disable-next-line import/no-unassigned-import +import 'react-router-dom'; + +declare module 'react-router-dom' { + import { type Location } from 'react-router-dom'; + + function useLocation(): Omit & { state: unknown }; +} diff --git a/packages/console/src/pages/Main/index.tsx b/packages/console/src/pages/Main/index.tsx index 5add1bf86..a2a8654a2 100644 --- a/packages/console/src/pages/Main/index.tsx +++ b/packages/console/src/pages/Main/index.tsx @@ -1,4 +1,9 @@ -import { BrowserRouter, Route, Routes } from 'react-router-dom'; +import { + Route, + RouterProvider, + createBrowserRouter, + createRoutesFromElements, +} from 'react-router-dom'; import { SWRConfig } from 'swr'; import Toast from '@/components/Toast'; @@ -14,23 +19,27 @@ import HandleSocialCallback from '../Profile/containers/HandleSocialCallback'; function Main() { const swrOptions = useSwrOptions(); + const router = createBrowserRouter( + createRoutesFromElements( + <> + } /> + } /> + } /> + }> + } /> + + + ), + { basename: getBasename() } + ); return ( - - - - - - } /> - } /> - } /> - }> - } /> - - - - - + + + + + + ); } diff --git a/packages/ui/package.json b/packages/ui/package.json index 3602bb06f..89ece99b1 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -77,7 +77,7 @@ "react-hook-form": "^7.34.0", "react-i18next": "^11.18.3", "react-modal": "^3.15.1", - "react-router-dom": "^6.2.2", + "react-router-dom": "^6.10.0", "react-string-replace": "^1.0.0", "react-timer-hook": "^3.0.5", "react-top-loading-bar": "^2.3.1", diff --git a/packages/ui/src/include.d/react-router-dom.d.ts b/packages/ui/src/include.d/react-router-dom.d.ts new file mode 100644 index 000000000..56d37327a --- /dev/null +++ b/packages/ui/src/include.d/react-router-dom.d.ts @@ -0,0 +1,16 @@ +/** + * This type definition file is a workaround for the fact that react-router-dom + * declares location status type as `any` instead of `unknown`, which ends up + * causing issues with strict type narrowing in TypeScript. + * + * Reference: https://github.com/remix-run/react-router/issues/10241 + */ + +// eslint-disable-next-line import/no-unassigned-import +import 'react-router-dom'; + +declare module 'react-router-dom' { + import { type Location } from 'react-router-dom'; + + function useLocation(): Omit & { state: unknown }; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 040413970..89eba557d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2970,8 +2970,8 @@ importers: specifier: ^8.1.3 version: 8.1.3(react@18.2.0) react-router-dom: - specifier: 6.3.0 - version: 6.3.0(react-dom@18.2.0)(react@18.2.0) + specifier: ^6.10.0 + version: 6.10.0(react-dom@18.2.0)(react@18.2.0) react-syntax-highlighter: specifier: ^15.5.0 version: 15.5.0(react@18.2.0) @@ -3952,8 +3952,8 @@ importers: specifier: ^3.15.1 version: 3.15.1(react-dom@18.2.0)(react@18.2.0) react-router-dom: - specifier: ^6.2.2 - version: 6.2.2(react-dom@18.2.0)(react@18.2.0) + specifier: ^6.10.0 + version: 6.10.0(react-dom@18.2.0)(react@18.2.0) react-string-replace: specifier: ^1.0.0 version: 1.0.0 @@ -7464,6 +7464,11 @@ packages: '@redis/client': 1.5.6 dev: false + /@remix-run/router@1.5.0: + resolution: {integrity: sha512-bkUDCp8o1MvFO+qxkODcbhSqRa6P2GXgrGZVpt0dCXNW2HCSCqYI0ZoAqEOSAjRWmmlKcYgFvN4B4S+zo/f8kg==} + engines: {node: '>=14'} + dev: true + /@rollup/plugin-commonjs@24.0.0(rollup@3.8.0): resolution: {integrity: sha512-0w0wyykzdyRRPHOb0cQt14mIBLujfAv6GgP6g8nvg/iBxEm112t3YPPq+Buqe2+imvElTka+bjNlJ/gB56TD8g==} engines: {node: '>=14.0.0'} @@ -16577,45 +16582,26 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: true - /react-router-dom@6.2.2(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-AtYEsAST7bDD4dLSQHDnk/qxWLJdad5t1HFa1qJyUrCeGgEuCSw0VB/27ARbF9Fi/W5598ujvJOm3ujUCVzuYQ==} + /react-router-dom@6.10.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-E5dfxRPuXKJqzwSe/qGcqdwa18QiWC6f3H3cWXM24qj4N0/beCIf/CWTipop2xm7mR0RCS99NnaqPNjHtrAzCg==} + engines: {node: '>=14'} peerDependencies: react: '>=16.8 || ^18.0.0' react-dom: '>=16.8' dependencies: - history: 5.3.0 + '@remix-run/router': 1.5.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - react-router: 6.2.2(react@18.2.0) + react-router: 6.10.0(react@18.2.0) dev: true - /react-router-dom@6.3.0(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==} - peerDependencies: - react: '>=16.8 || ^18.0.0' - react-dom: '>=16.8' - dependencies: - history: 5.3.0 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-router: 6.3.0(react@18.2.0) - dev: true - - /react-router@6.2.2(react@18.2.0): - resolution: {integrity: sha512-/MbxyLzd7Q7amp4gDOGaYvXwhEojkJD5BtExkuKmj39VEE0m3l/zipf6h2WIB2jyAO0lI6NGETh4RDcktRm4AQ==} + /react-router@6.10.0(react@18.2.0): + resolution: {integrity: sha512-Nrg0BWpQqrC3ZFFkyewrflCud9dio9ME3ojHCF/WLsprJVzkq3q3UeEhMCAW1dobjeGbWgjNn/PVF6m46ANxXQ==} + engines: {node: '>=14'} peerDependencies: react: '>=16.8 || ^18.0.0' dependencies: - history: 5.3.0 - react: 18.2.0 - dev: true - - /react-router@6.3.0(react@18.2.0): - resolution: {integrity: sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==} - peerDependencies: - react: '>=16.8 || ^18.0.0' - dependencies: - history: 5.3.0 + '@remix-run/router': 1.5.0 react: 18.2.0 dev: true