Skip to content

Commit

Permalink
fix: Avoid swapping routes if component hasn't changed
Browse files Browse the repository at this point in the history
Co-authored-by: Jason Miller <developit@users.noreply.github.com>
  • Loading branch information
rschristian and developit committed Apr 8, 2024
1 parent 22df871 commit 2e4d850
Showing 1 changed file with 21 additions and 10 deletions.
31 changes: 21 additions & 10 deletions src/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,24 +117,33 @@ export function Router(props) {
// was the most recent render successful (did not suspend):
const didSuspend = useRef();
didSuspend.current = false;

useMemo(() => {
// This hack prevents Preact from diffing when we swap `cur` to `prev`:
if (this.__v && this.__v.__k) this.__v.__k.reverse();

count.current++;
prev.current = cur.current;
}, [url]);
// has the route component changed
const routeChanged = useRef(false);

let pr, d, m;
toChildArray(props.children).some(vnode => {
const matches = exec(rest, vnode.props.path, (m = { ...vnode.props, path: rest, query, params, rest: '' }));
if (matches) return (pr = cloneElement(vnode, m));
if (vnode.props.default) d = cloneElement(vnode, m);
});

let incoming = pr || d;
useMemo(() => {
prev.current = cur.current;

// Only mark as an update if the route component changed.
const outgoing = prev.current && prev.current.props.children;
if (!outgoing || !incoming || incoming.type !== outgoing.type || incoming.props.component !== outgoing.props.component) {
// This hack prevents Preact from diffing when we swap `cur` to `prev`:
if (this.__v && this.__v.__k) this.__v.__k.reverse();
count.current++;
routeChanged.current = true;
}
}, [url]);

const isHydratingSuspense = cur.current && cur.current.__u & MODE_HYDRATE && cur.current.__u & MODE_SUSPENDED;
const isHydratingBool = cur.current && cur.current.__h;
cur.current = h(RouteContext.Provider, { value: m }, pr || d);
cur.current = h(RouteContext.Provider, { value: m }, incoming);
if (isHydratingSuspense) {
cur.current.__u |= MODE_HYDRATE;
cur.current.__u |= MODE_SUSPENDED;
Expand Down Expand Up @@ -220,7 +229,9 @@ export function Router(props) {
}, [path, wasPush, c]);

// Note: curChildren MUST render first in order to set didSuspend & prev.
return [h(RenderRef, { r: cur }), h(RenderRef, { r: prev })];
return routeChanged.current
? [h(RenderRef, { r: cur }), h(RenderRef, { r: prev })]
: h(RenderRef, { r: cur });
}

const MODE_HYDRATE = 1 << 5;
Expand Down

0 comments on commit 2e4d850

Please sign in to comment.