Skip to content

Commit 5952af9

Browse files
author
Leonardo Rick
committed
feat(useNavigate): improve useNavigate to check if route exists in ember
1 parent 5609cbe commit 5952af9

File tree

7 files changed

+113
-9
lines changed

7 files changed

+113
-9
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ node_modules/
1212
coverage/
1313
npm-debug.log*
1414
yarn-error.log
15+
.yalc
1516

1617
# ember-try
1718
/.node_modules.ember-try/

pnpm-lock.yaml

Lines changed: 39 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

react-migration-toolkit/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@qonto/react-migration-toolkit",
3-
"version": "3.0.0",
3+
"version": "3.0.1",
44
"description": "A toolkit to help migrate Ember components to React",
55
"keywords": [
66
"ember-addon"
@@ -137,9 +137,10 @@
137137
}
138138
},
139139
"peerDependencies": {
140+
"ember-intl": "^7.0.0 && <7.0.8",
140141
"ember-source": "^3.28.0 || ^4.0.0 || ^5.0.0",
141142
"react-intl": "^6.6.8",
142-
"ember-intl": "^7.0.0 && <7.0.8"
143+
"react-router": "7.6.3"
143144
},
144145
"peerDependenciesMeta": {
145146
"react-intl": {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export { useEmberService } from './use-ember-service';
22
export { useApplicationInstance } from './use-application-instance';
33
export { useNavigate } from './use-navigate';
4+
export { useIsEmberRoute } from './use-is-ember-route';
45
export { useRouter } from './use-router';
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { useLocation, useInRouterContext } from 'react-router';
2+
import type { UrlObject } from '../types/router';
3+
import { useEmberService } from './use-ember-service';
4+
import { useCallback } from 'react';
5+
/**
6+
* Determines whether the current route is handled by the Ember router.
7+
*
8+
* This hook inspects the application's router to check if the current path
9+
* matches any Ember route handler, excluding those that contain "react" in their name.
10+
* We need to apply a regex to explicitly exclude 'react' routes because,
11+
* if not, 'react-fallback' and similar named routes would match would match.
12+
*
13+
* @returns true if the current route is an Ember route (not a React route), otherwise false.
14+
*
15+
* @remarks
16+
* This is useful for hybrid applications where both Ember and React routes may coexist,
17+
* and you need to conditionally render or handle logic based on the routing system in use.
18+
*/
19+
export const useIsEmberRoute = (): ((
20+
pathname?: string | UrlObject,
21+
) => boolean) => {
22+
// avoids Uncaught Error: useLocation() may be used only in the context of a <Router> component
23+
if (!useInRouterContext()) {
24+
return () => true;
25+
}
26+
const location = useLocation();
27+
const emberRouter = useEmberService('router');
28+
29+
return useCallback(
30+
(path?: string | UrlObject) => {
31+
// if inspection isn't possible, we assume Ember for backward compatibility
32+
if (!emberRouter?.recognize) return true;
33+
34+
const targetPath =
35+
typeof path === 'string' ? path : path?.pathname || location.pathname;
36+
const routeName = emberRouter.recognize(targetPath).name;
37+
return Boolean(routeName) && !/react/.exec(routeName);
38+
},
39+
[emberRouter, location.pathname],
40+
);
41+
};

react-migration-toolkit/src/react/hooks/use-navigate.ts

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,36 @@ import {
33
PolymorphicNavigateContext,
44
type PolymorphicNavigate,
55
} from '../contexts/polymorphic-navigate-context';
6+
import type { NavigateOptions } from 'react-router';
7+
import {
8+
useInRouterContext,
9+
useNavigate as useReactRouterNavigate,
10+
} from 'react-router';
11+
import { useIsEmberRoute } from './use-is-ember-route';
12+
import type { UrlObject } from '../types/router';
613

714
export const useNavigate = (): PolymorphicNavigate => {
8-
const navigate = useContext(PolymorphicNavigateContext);
9-
if (!navigate) {
15+
const contextNavigate = useContext(PolymorphicNavigateContext);
16+
if (!contextNavigate) {
1017
throw new Error(
11-
'this hook can only be used with PolymorphicNavigateProvider',
18+
'useNavigate hook can only be used with PolymorphicNavigateProvider',
1219
);
1320
}
14-
return navigate;
21+
22+
// avoids Uncaught Error: useNavigate() may be used only in the context of a <Router> component
23+
if (!useInRouterContext()) {
24+
return (to: string | UrlObject, options?: NavigateOptions) => {
25+
return contextNavigate(to, options);
26+
};
27+
}
28+
29+
const isEmberRoute = useIsEmberRoute();
30+
const reactRouterNavigate = useReactRouterNavigate();
31+
32+
return (to: string | UrlObject, options?: NavigateOptions) => {
33+
if (isEmberRoute(to)) {
34+
return contextNavigate(to, options);
35+
}
36+
return reactRouterNavigate(to, options);
37+
};
1538
};

react-migration-toolkit/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"jsx": "react-jsx",
99
"allowJs": true,
1010
"declarationDir": "declarations",
11+
"lib": ["dom", "dom.iterable", "esnext"],
1112
/**
1213
https://www.typescriptlang.org/tsconfig#noEmit
1314

0 commit comments

Comments
 (0)