Skip to content

Commit 43473c6

Browse files
rmarscherdai-shi
andauthored
fix: update url after route change (#1459)
For #1437. --------- Co-authored-by: Daishi Kato <[email protected]>
1 parent 5c94a84 commit 43473c6

File tree

2 files changed

+89
-65
lines changed

2 files changed

+89
-65
lines changed
Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
import type { Middleware } from 'waku/config';
22

3+
// BASE_RSC_PATH + encodeRscPath(rscPath)
4+
const redirects = {
5+
'/redirect': '/exists',
6+
'/RSC/R/redirect.txt': '/RSC/R/exists.txt',
7+
'/broken-redirect': '/broken',
8+
'/RSC/R/broken-redirect.txt': '/RSC/R/broken.txt',
9+
};
10+
311
const redirectsMiddleware: Middleware = () => async (ctx, next) => {
4-
switch (ctx.req.url.pathname) {
5-
case '/redirect':
6-
ctx.res.status = 302;
7-
ctx.res.headers = {
8-
Location: '/exists',
9-
};
10-
break;
11-
case '/broken-redirect':
12-
ctx.res.status = 302;
13-
ctx.res.headers = {
14-
Location: '/broken',
15-
};
16-
break;
17-
default:
18-
return await next();
12+
if (ctx.req.url.pathname in redirects) {
13+
const pathname = ctx.req.url.pathname as keyof typeof redirects;
14+
const url = new URL(ctx.req.url);
15+
url.pathname = redirects[pathname];
16+
ctx.res.status = 302;
17+
ctx.res.headers = {
18+
Location: url.toString(),
19+
};
20+
return;
1921
}
22+
return await next();
2023
};
2124

2225
export default redirectsMiddleware;

packages/waku/src/router/client.ts

Lines changed: 71 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -151,18 +151,21 @@ export function useRouter() {
151151
},
152152
) => {
153153
const url = new URL(to, window.location.href);
154-
const newPath = url.pathname !== window.location.pathname;
155-
window.history.pushState(
156-
{
157-
...window.history.state,
158-
waku_new_path: newPath,
159-
},
160-
'',
161-
url,
162-
);
154+
const currentPath = window.location.pathname;
155+
const newPath = url.pathname !== currentPath;
163156
await changeRoute(parseRoute(url), {
164157
shouldScroll: options?.scroll ?? newPath,
165158
});
159+
if (window.location.pathname === currentPath) {
160+
window.history.pushState(
161+
{
162+
...window.history.state,
163+
waku_new_path: newPath,
164+
},
165+
'',
166+
url,
167+
);
168+
}
166169
},
167170
[changeRoute],
168171
);
@@ -180,11 +183,14 @@ export function useRouter() {
180183
},
181184
) => {
182185
const url = new URL(to, window.location.href);
183-
const newPath = url.pathname !== window.location.pathname;
184-
window.history.replaceState(window.history.state, '', url);
186+
const currentPath = window.location.pathname;
187+
const newPath = url.pathname !== currentPath;
185188
await changeRoute(parseRoute(url), {
186189
shouldScroll: options?.scroll ?? newPath,
187190
});
191+
if (window.location.pathname === currentPath) {
192+
window.history.replaceState(window.history.state, '', url);
193+
}
188194
},
189195
[changeRoute],
190196
);
@@ -331,19 +337,26 @@ export function Link({
331337
const route = parseRoute(url);
332338
prefetchRoute(route);
333339
startTransitionFn(async () => {
334-
const newPath = url.pathname !== window.location.pathname;
335-
window.history.pushState(
336-
{
337-
...window.history.state,
338-
waku_new_path: newPath,
339-
},
340-
'',
341-
url,
342-
);
343-
await changeRoute(route, {
344-
shouldScroll: scroll ?? newPath,
345-
unstable_startTransition: startTransitionFn,
346-
});
340+
const currentPath = window.location.pathname;
341+
const newPath = url.pathname !== currentPath;
342+
try {
343+
await changeRoute(route, {
344+
shouldScroll: scroll ?? newPath,
345+
unstable_startTransition: startTransitionFn,
346+
});
347+
} finally {
348+
if (window.location.pathname === currentPath) {
349+
// Update history if it wasn't already updated
350+
window.history.pushState(
351+
{
352+
...window.history.state,
353+
waku_new_path: newPath,
354+
},
355+
'',
356+
url,
357+
);
358+
}
359+
}
347360
});
348361
}
349362
};
@@ -474,15 +487,8 @@ const Redirect = ({
474487
window.location.replace(to);
475488
return;
476489
}
477-
const newPath = url.pathname !== window.location.pathname;
478-
window.history.pushState(
479-
{
480-
...window.history.state,
481-
waku_new_path: newPath,
482-
},
483-
'',
484-
url,
485-
);
490+
const currentPath = window.location.pathname;
491+
const newPath = url.pathname !== currentPath;
486492
changeRoute(parseRoute(url), { shouldScroll: newPath })
487493
.then(() => {
488494
// FIXME: As we understand it, we should have a proper solution.
@@ -492,6 +498,18 @@ const Redirect = ({
492498
})
493499
.catch((err) => {
494500
console.log('Error while navigating to redirect:', err);
501+
})
502+
.finally(() => {
503+
if (window.location.pathname === currentPath) {
504+
window.history.replaceState(
505+
{
506+
...window.history.state,
507+
waku_new_path: newPath,
508+
},
509+
'',
510+
url,
511+
);
512+
}
495513
});
496514
}, [error, to, reset, changeRoute]);
497515
return null;
@@ -613,6 +631,7 @@ const handleScroll = () => {
613631
const InnerRouter = ({ initialRoute }: { initialRoute: RouteProps }) => {
614632
const elementsPromise = useElementsPromise();
615633
const [has404, setHas404] = useState(false);
634+
const requestedRouteRef = useRef<RouteProps>(initialRoute);
616635
const staticPathSetRef = useRef(new Set<string>());
617636
const cachedIdSetRef = useRef(new Set<string>());
618637
useEffect(() => {
@@ -679,11 +698,9 @@ const InnerRouter = ({ initialRoute }: { initialRoute: RouteProps }) => {
679698
elements;
680699
if (routeData) {
681700
const [path, query] = routeData as [string, string];
682-
// FIXME this check here seems ad-hoc (less readable code)
683701
if (
684-
window.location.pathname !== path ||
685-
(!isStatic &&
686-
window.location.search.replace(/^\?/, '') !== query)
702+
requestedRouteRef.current.path !== path ||
703+
(!isStatic && requestedRouteRef.current.query !== query)
687704
) {
688705
locationListeners.forEach((listener) =>
689706
listener(path, query),
@@ -767,6 +784,7 @@ const InnerRouter = ({ initialRoute }: { initialRoute: RouteProps }) => {
767784
const refetching = useRef<[onFinish?: () => void] | null>(null);
768785
const changeRoute: ChangeRoute = useCallback(
769786
async (route, options) => {
787+
requestedRouteRef.current = route;
770788
executeListeners('start', route);
771789
const startTransitionFn =
772790
options.unstable_startTransition || ((fn: TransitionFunction) => fn());
@@ -827,22 +845,25 @@ const InnerRouter = ({ initialRoute }: { initialRoute: RouteProps }) => {
827845
url.pathname = path;
828846
url.search = query;
829847
url.hash = '';
830-
if (path !== '/404') {
831-
window.history.pushState(
832-
{
833-
...window.history.state,
834-
waku_new_path: url.pathname !== window.location.pathname,
835-
},
836-
'',
837-
url,
838-
);
839-
}
840848
changeRoute(parseRoute(url), {
841849
skipRefetch: true,
842850
shouldScroll: false,
843-
}).catch((err) => {
844-
console.log('Error while navigating to new route:', err);
845-
});
851+
})
852+
.catch((err) => {
853+
console.log('Error while handling location listeners:', err);
854+
})
855+
.finally(() => {
856+
if (path !== '/404') {
857+
window.history.pushState(
858+
{
859+
...window.history.state,
860+
waku_new_path: url.pathname !== window.location.pathname,
861+
},
862+
'',
863+
url,
864+
);
865+
}
866+
});
846867
};
847868
if (refetching.current) {
848869
refetching.current.push(fn);

0 commit comments

Comments
 (0)