Routing - Qwik for Angular Developers
In this article we will look at how routing works in Qwik applications. We will look at how to define routes, how to navigate between routes and how to access route parameters and use route loaders. It does not cover Qwik's layout functionality and the route endpoints.
Qwik is separated into two parts, the Qwik core framework and Qwik City, which is a collection of additional functionality that is useful for building applications. Qwik City contains the routing. Let's assume you have already a Qwik app up and running.
Route definition
Hey Angular dev! How are you writing your route definitions? I bet you are using the
RouterModule and pass an array of routes to the forRoot
or forChild
method. That's
at least the most typical way for routing in Angular applications. In Qwik we are using
the filesystem to define the routes. That's right, no routes array to configure here.
Instead we are using the filesystem to define the routes. Let's look at an example. The
routes are all defined in the routes
folder.
/src
/routes
/home
index.tsx
/about
index.mdx
/contact
index.tsx
The index.tsx
and index.mdx
files are both route endpoints. The index.mdx
file
is an extended markdown file, which is able to render components inside the markdown.
This is also a feature of Qwik City. The index.tsx
file is a regular Qwik component.
Routes must be named index
plus file extension. You can not define
/src/routes/about.tsx
for example.
Route paramters
In Angular you would define your routes in the following way:
const routes: Routes = [{ path: 'user/:id', component: UserComponent }];
Here we are defining a route with a parameter called id
. Inside of the UserComponent you can access the
the id
parameter by injecting the ActivatedRoute
and access either the current route snapshot or listening to the
params stream. The Qwik way of defining a route with a parameter is to use a folder with the parameter name. With
square brackets around the parameter name you can indicate that this path segment is a parameter.
/src/routes/user/[id]/index.tsx
Inside of your component you can now access the parameter by using the useLocation
hook as follows
import { component$ } from '@builder.io/qwik';
import { useLocation } from '@builder.io/qwik-city';
export default component$(() => {
const location = useLocation();
return <>User id: {location.params.id}</>;
});
Route loaders
This is probably the most interesting part of the routing topic and differs from Angular. Maybe similar functionality is available in Angular Universal, but honestly I don't know.
The two most common ways of loading route specific data is to either use a route resolver or to trigger an API request via a service based on the route parameter. The service usually triggers an HTTP request to the server.
Qwik provides so called route loaders to load data for a route. A route loader is a function that is called when a route is loaded inside the component. The difference to a route resolver is that this route loader is executed on the server. Qwik's documentation says
[...] Qwik routeLoaders should be always understood in the context of loading data in the server that is later consumed by a Qwik Component [...]
Let's have a look. Inside of the components index.tsx
file you can create an exported function using the
routeLoader$
. The function can be async
and can return any JSON serializable data.
import { routeLoader$ } from '@builder.io/qwik-city';
export const useUsersData = routeLoader$(async () => {
// Here you can access the database or trigger API requests, etc.
// You can also access the file system using Node APIs. Keep in mind that
// some hosting providers do not support Node APIs, especially on the so called "edge".
return [
{ id: 1, name: 'Hans Wurst' },
{ id: 2, name: 'Klaus Kleber' },
];
});
Now we can use this route loader inside of our component. Imagine that we have created a new hook using our defined route loader.
import { component$ } from '@builder.io/qwik';
// Previously defined route loader
export default component$(() => {
const users = useUsersData();
return (
<>
<h1>Users</h1>
<ul>
{users.value.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</>
);
});
The loader function returns a signal, which is an asynchronous value. Access the signal's value using
the value
property.
Takeaways
- Qwik uses the filesystem to define routes
- Qwik uses route loaders to load data for a route
- Route loaders are called inside the component and executed on the server. They are no HTTP endpoints. They are a Qwik internal communication channel of loading data for a route.
- Route parameters are defined using a folder with square brackets around the parameter name
If you have any questions feel free to drop me a message on LinkedIn or Twitter.
Have an awesome day!