Troubleshooting
Common symptoms, what causes them, and how to fix them.
On this page
Clicking a link reloads the whole page
Cause
No pattern in the route table fits the link’s path. The router takes only navigations to paths the table answers, and leaves the rest to the browser as an ordinary page load. When the app is served below a base path, it does not take paths outside that either.
Fix
Add the pattern to the route table. Build links with href and register the table on Register, and a pattern the table lacks shows up as a type error.
A link to a file shows the /* page instead of the file
Cause
The /* at the end of the route table fits every path, so the router takes a link to a file the host serves as well.
Fix
Give the link the download attribute. The browser then reports a download, and the router leaves it alone.
/products/new renders the /products/:id page
Cause
Matching walks the route table from the top and takes the first pattern that fits. With /products/:id written first, new fits :id.
Fix
Write a literal pattern such as /products/new before the :id pattern.
useParams throws “rendered under”
Cause
The pattern given to useParams is not the pattern of the page the component is rendering under. It happens in a component shared by several pages, or in a layout.
Fix
Call it in the page component, with that page’s pattern. In a component shared by several pages, read untyped params with useRoute, or check the open page with useMatch.
useRoute or useParams throws under the framework
Cause
Under @k8ordo/static and @k8ordo/server, the browser has neither the route table nor a match. Both hooks read the match <Router> holds, so they find nothing and throw.
Fix
A page receives params as a prop. To know where you are in a Client Component, use usePathname or useMatch.
usePathname throws “needs <Router> above it”
Cause
During a server render or hydration, the browser’s URL cannot be read. usePathname then reads the path <Router> or the framework’s runtime provides, and neither is above it.
Fix
Use it under <Router> or in a page the framework renders. In a host of your own built on useInterceptedNavigation, provide the path being rendered through <PathnameProvider>.
The history option has no effect on a bound navigateTo
Cause
When the pattern names a param, the second argument is always read as params, even with every param bound. Options passed second become params, and history is ignored.
Fix
Pass undefined second and the options third. With the type check in place, options in second place are a type error.
On a slow navigation, the current link changes too early
Cause
A navigation changes the URL first, and the new page appears once it is ready. usePathname and useMatch read the URL, so they return the new path while the previous page is still showing, in the same order as the address bar.
Fix
To show that a page is loading, check usePendingPathname. For a navigation you started, await navigateTo’s finished.
Nothing shows while a React.lazy page loads
Cause
An object with an error wraps the pages below in a <Suspense> whose fallback is null. A React.lazy page that suspends there never reaches a layout’s <Suspense> above, and nothing shows.
Fix
Give the same object a loading, or put a <Suspense> further down.
finished rejects with an AbortError
Cause
Another navigation started before this one finished. The overtaken navigation is abandoned, and its finished rejects with the abort reason.
Fix
Where finished can be overtaken, ignore a DOMException named AbortError and rethrow anything else.
Every button press cross-fades the whole page
Cause
The <ViewTransition> runs for transitions other than page changes. A pending action of @k8ordo/ui’s Button is a transition too.
Fix
Set the <ViewTransition>’s default to none and pass { navigation: 'auto', default: 'none' } to update. It then runs only for the navigation type the router adds.
Changing a search does not clear the error
Cause
The route table’s error clears when you move to another page. An update that changes only the query string is not a page change, so the error stays.
Fix
Call the reset the error component receives, and the page renders again in place.
A pattern the table lacks passes despite Register
Cause
The file holding the registration is not part of what TypeScript checks. Under the framework, .k8ordo starts with a dot, so naming just the directory in tsconfig.json’s include skips it.
Fix
Put the file inside what include covers. Under the framework, list the glob .k8ordo/**/*.ts in include.