mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
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 <charleszhao@silverhand.io>
This commit is contained in:
parent
4b6ad4c8c5
commit
e97fe2e1f3
7 changed files with 96 additions and 124 deletions
|
@ -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",
|
||||
|
|
|
@ -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<Transition>();
|
||||
|
||||
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 (
|
||||
<ConfirmModal
|
||||
isOpen={displayAlert}
|
||||
isOpen={blocker.state === 'blocked'}
|
||||
confirmButtonText="general.leave_page"
|
||||
cancelButtonText="general.stay_on_page"
|
||||
onCancel={stayOnPage}
|
||||
onConfirm={leavePage}
|
||||
onCancel={blocker.reset}
|
||||
onConfirm={blocker.proceed}
|
||||
>
|
||||
{t('general.unsaved_changes_warning')}
|
||||
</ConfirmModal>
|
||||
|
|
16
packages/console/src/include.d/react-router-dom.d.ts
vendored
Normal file
16
packages/console/src/include.d/react-router-dom.d.ts
vendored
Normal file
|
@ -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<Location, 'state'> & { state: unknown };
|
||||
}
|
|
@ -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(
|
||||
<>
|
||||
<Route path="callback" element={<Callback />} />
|
||||
<Route path="welcome" element={<Welcome />} />
|
||||
<Route path="handle-social" element={<HandleSocialCallback />} />
|
||||
<Route element={<AppContent />}>
|
||||
<Route path="/*" element={<ConsoleContent />} />
|
||||
</Route>
|
||||
</>
|
||||
),
|
||||
{ basename: getBasename() }
|
||||
);
|
||||
|
||||
return (
|
||||
<BrowserRouter basename={getBasename()}>
|
||||
<SWRConfig value={swrOptions}>
|
||||
<AppBoundary>
|
||||
<Toast />
|
||||
<Routes>
|
||||
<Route path="callback" element={<Callback />} />
|
||||
<Route path="welcome" element={<Welcome />} />
|
||||
<Route path="handle-social" element={<HandleSocialCallback />} />
|
||||
<Route element={<AppContent />}>
|
||||
<Route path="/*" element={<ConsoleContent />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</AppBoundary>
|
||||
</SWRConfig>
|
||||
</BrowserRouter>
|
||||
<SWRConfig value={swrOptions}>
|
||||
<AppBoundary>
|
||||
<Toast />
|
||||
<RouterProvider router={router} />
|
||||
</AppBoundary>
|
||||
</SWRConfig>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
16
packages/ui/src/include.d/react-router-dom.d.ts
vendored
Normal file
16
packages/ui/src/include.d/react-router-dom.d.ts
vendored
Normal file
|
@ -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<Location, 'state'> & { state: unknown };
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue