Skip to content

Commit 8a3a2e5

Browse files
authored
feat: support modifyRoutes hook for router v5 (#3666)
1 parent 8f2965f commit 8a3a2e5

File tree

6 files changed

+81
-15
lines changed

6 files changed

+81
-15
lines changed

.changeset/serious-bobcats-reflect.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@modern-js/runtime': minor
3+
---
4+
5+
feat: support modifyRoutes hook for router v5
6+
feat: 为 router v5 支持 modifyRoutes hook

packages/runtime/plugin-router-v5/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"test": "jest --passWithNoTests"
6262
},
6363
"dependencies": {
64+
"@modern-js/plugin": "workspace:*",
6465
"@modern-js/types": "workspace:*",
6566
"@modern-js/utils": "workspace:*",
6667
"@types/history": "^4.7.9",
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { createWaterfall } from '@modern-js/plugin';
2+
import { RouteProps } from 'react-router-dom';
3+
4+
const modifyRoutesHook = createWaterfall<RouteProps[]>();
5+
6+
export { modifyRoutesHook };

packages/runtime/plugin-router-v5/src/runtime/plugin.tsx

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { RuntimeReactContext, isBrowser } from '@modern-js/runtime';
1818
import type { Plugin } from '@modern-js/runtime';
1919
import { parsedJSONFromElement } from '@modern-js/utils/runtime-browser';
2020
import { renderRoutes, getLocation, urlJoin } from './utils';
21+
import { modifyRoutesHook } from './hooks';
2122

2223
declare global {
2324
interface Window {
@@ -75,6 +76,7 @@ export const routerPlugin = ({
7576
createRoutes,
7677
historyOptions = {},
7778
}: RouterConfig): Plugin => {
79+
const originRoutes = routesConfig?.routes || [];
7880
const isBrow = isBrowser();
7981

8082
const select = (pathname: string) =>
@@ -86,7 +88,10 @@ export const routerPlugin = ({
8688

8789
return {
8890
name: '@modern-js/plugin-router',
89-
setup: () => {
91+
registerHook: {
92+
modifyRoutes: modifyRoutesHook,
93+
},
94+
setup: api => {
9095
return {
9196
init({ context }, next) {
9297
context.router = {
@@ -111,16 +116,20 @@ export const routerPlugin = ({
111116
(supportHtml5History
112117
? createBrowserHistory(historyOptions)
113118
: createHashHistory(historyOptions));
114-
115-
return (props: any) => (
116-
<Router history={history}>
117-
{createRoutes ? (
118-
<App {...props} Component={createRoutes()} />
119-
) : (
120-
<App {...props}>{renderRoutes(routesConfig, props)}</App>
121-
)}
122-
</Router>
123-
);
119+
return (props: any) => {
120+
const runner = (api as any).useHookRunners();
121+
const routes = runner.modifyRoutes(originRoutes);
122+
routesConfig && (routesConfig.routes = routes);
123+
return (
124+
<Router history={history}>
125+
{createRoutes ? (
126+
<App {...props} Component={createRoutes()} />
127+
) : (
128+
<App {...props}>{renderRoutes(routesConfig, props)}</App>
129+
)}
130+
</Router>
131+
);
132+
};
124133
}
125134
return (props: any) => {
126135
const runtimeContext = useContext(RuntimeReactContext);
@@ -133,6 +142,9 @@ export const routerPlugin = ({
133142
baseUrl === '/'
134143
? urlJoin(baseUrl, historyOptions.basename as string)
135144
: baseUrl;
145+
const runner = (api as any).useHookRunners();
146+
const routes = runner.modifyRoutes(originRoutes);
147+
routesConfig && (routesConfig.routes = routes);
136148
return (
137149
<StaticRouter
138150
basename={basename === '/' ? '' : basename}
@@ -148,18 +160,16 @@ export const routerPlugin = ({
148160
);
149161
};
150162
};
151-
let RouteApp = getRouteApp();
152163

164+
let RouteApp = getRouteApp();
153165
if (App) {
154166
RouteApp = hoistNonReactStatics(RouteApp, App);
155167
}
156-
157168
if (routesConfig?.globalApp) {
158169
return next({
159170
App: hoistNonReactStatics(RouteApp, routesConfig.globalApp),
160171
});
161172
}
162-
163173
return next({
164174
App: RouteApp,
165175
});

packages/runtime/plugin-router-v5/tests/router.test.tsx

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React from 'react';
22
import { render, fireEvent, screen } from '@testing-library/react';
33
import { createBrowserHistory } from 'history';
44
import { createApp, createPlugin } from '@modern-js/runtime';
5-
import createRouterPlugin, { useLocation } from '../src/runtime';
5+
import createRouterPlugin, { RouteProps, useLocation } from '../src/runtime';
66
import { useHistory } from '../src';
77
import { DefaultNotFound } from '../src/runtime/DefaultNotFound';
88

@@ -186,4 +186,45 @@ describe('@modern-js/plugin-router-v5', () => {
186186
const { container } = render(<DefaultNotFound />);
187187
expect(container.firstChild?.textContent).toEqual('404');
188188
});
189+
190+
it('support modify routes', () => {
191+
type ModifyRoutesFn = (routes: RouteProps[]) => RouteProps[];
192+
const expectedText = 'modify routes';
193+
let modifyFn: ModifyRoutesFn | null = null;
194+
const modifyRoutes = (fn: ModifyRoutesFn) => {
195+
modifyFn = fn;
196+
};
197+
198+
modifyRoutes(routes => {
199+
routes[0].component = function () {
200+
return <>{expectedText}</>;
201+
};
202+
return routes;
203+
});
204+
205+
const AppWrapper = createApp({
206+
plugins: [
207+
createPlugin(() => ({
208+
hoc: ({ App: App1 }, next) => next({ App: App1 }),
209+
modifyRoutes(routes: RouteProps[]) {
210+
return modifyFn?.(routes);
211+
},
212+
})),
213+
createRouterPlugin({
214+
routesConfig: { routes: [{ path: '/', component: App as any }] },
215+
}),
216+
],
217+
})(App);
218+
219+
interface Props {
220+
children: React.ReactNode;
221+
}
222+
function App({ children }: Props) {
223+
return <div>{children}</div>;
224+
}
225+
const { container } = render(<AppWrapper test={1} />);
226+
227+
expect(container.firstChild?.textContent).toBe(`${expectedText}`);
228+
expect(container.innerHTML).toBe(`<div>${expectedText}</div>`);
229+
});
189230
});

pnpm-lock.yaml

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

0 commit comments

Comments
 (0)