Routing & Navigation
Edit this pageSolid Router simplifies routing in Solid applications to help developers manage navigation and rendering by defining routes using JSX or objects passed via props.
Getting Started
Set Up the Router
- Install
@solidjs/router
. This package is not included by default.
- To use the router, import the
Router
component to wrap the root component. This allows the routes to be displayed throughout the entire application.
Configure the Routes
Solid Router offers a convenient way to configure routes using JSX
syntax:
- Using the
Routes
component, you can specify where the routes should appear in the application:
- The
Route
component takes apath
prop, which specifies what path or element to render when navigated to. When this path is successfully matched, thecomponent
orelement
prop will be triggered, rendering what it corresponds to. For grouping multiple routes, or for nesting, theRoutes
component must be used. For example:
Creating links to Routes
A
Component
The The A
component creates an anchor tag that navigates to routes within an application.
Additionally, the component takes in an href
prop which acts as the URL path that the link will navigate to.
The A
component can also take in the activeClass
prop, which is a class that will be applied when the current location matches the href
prop.
A
Component Props
prop | type | description |
---|---|---|
href | string | Indicates the URL path to navigate to, which must start with a forward slash ("/"). |
noScroll | boolean | If true , the default behavior of scrolling to the top of the new page will be turned off. |
replace | boolean | If set to true , the new page will not be added to the browser history, preventing the back button from navigate to the previous route. By default, the new page is added to the browser history. |
state | serializable object | Passes a serialized object to the history stack during navigation. When the user navigates to the new state, an event is triggered, granting access to a copy of the state object associated with that particular entry in the browsing history. See history.pushState() for more info. |
inactiveClass | string | Will specifies the CSS class to apply when the location and href prop do not match. |
activeClass | string | The CSS class that will be applied when the location and href prop match. |
end | boolean | When set to true , the link is considered active only when the current location exactly matches the href . However, when set to false , the link is considered active if the current location starts with the href value. |
Navigate
component
The Solid router offers a Navigate
component that works similarly to A
, however, it will immediately navigate to the provided path as soon as the component is rendered.
In addition to the href
prop, there is an additional option to pass a function to href
that returns a path to navigate to.
Nested Routes
Solid Router supports nested routes, allowing for more complex routing structures.
However, only the innermost Route
nodes will be given a route.
To ensure the parent has its own route, it must be specified separately.
<Outlet />
Component
The Nested routes can also take advantage of the <Outlet />
component to render the nested content within a parent component.
The <Outlet />
component serves as a placeholder that will be be replaced with the content of the matched child route.
In this example, the <Outlet />
component is used to specify where the content of the child routes should be rendered within the PageWrapper
component.
When the /about
route is matched, the PageWrapper
component will be rendered, and the content of the child routes (About
and Me
) will be rendered inside the component.
This approach allows you to define a shared layout or container component for a group of nested routes and render the specific element based on the child routes.
As long as there are the appropriate parent component <Outlet />
placeholders defined at each level, you can nest routes indefinitely using this approach.
Dynamic Routing
Dynamic routing lets an application handle URLs where some segments are not known ahead of time.
You can create a dynamic route by using a colon (:) before a segment in the path
prop of a Route
component.
This indicates that the segment can be any string.
In the example above, the :id
in the /user/:id
path will be treated as a parameter.
As long as the URL matches this pattern, the User component will be displayed.
Accessing parameters
In cases where you may need to access a dynamic route's parameters within your components, the useParams
primitive is available.
And once the parameters have been accessed using useParams
, they can be used within your component:
This primtive can be especially useful with other Solid primitives, such as createResource
and createSignal
, which can create dynamic behaviours based on the route parameters.
Every time the id
parameter changes in this example, the fetchUser
function is called to fetch the new user data.
Validating routes
When working with dynamic routes, it is often necessary to validate the route parameters to ensure they meet certain criteria.
This task can be performed through MatchFilters
.
MatchFilters
provides the option to define validation rules for each parameter in the route path.
By including the matchFilters={filters}
prop in the <Route>
component, the parameters in the route path are automatically validated against their respective filters.
If any validation fails, the route will not be matched.
In this example, the filters
object defines the validation rules for each parameter:
- The
parent
parameter allows only the values"mom"
or"dad"
. - The
id
parameter allows only numeric values. - The
withHtmlExtension
parameter is validated using a custom function that checks for a length greater than 5 and a".html"
extension.
Creating optional routes
Routes can be specified as optional by adding ?
to the end of a parameter name for more flexible routing patterns.
This is especially useful when specific segments of the path may or may not be present.
Specifying wildcard routes
Wildcard routes allow matching of any descendent within a given path.
The wildcard token (*
) can be used to represent any value in that segment of the path.
Additionally, this value can be exposed as a parameter to the component.
In this example, the route path "foo/*"
matches any path that begins with "foo"
.
This includes paths like "foo/"
, "foo/a/"
, or "foo/a/b/c"
.
To expose the wildcard part of the path to the component as a parameter, you can do the following:
Note: The wildcard token must be the last part of the path; foo/*any/bar
would not create any routes.
Defining Multiple Paths
Routes can be defined with multiple paths using an array.
This feature allows a Route
component to remain mounted and avoid re-rendering when switching between multiple locations that match any of the predetermined paths.
Using multiple paths can be useful when the same component and state are to be shared between different URLs that serve a similar purpose.
Creating data components
Solid Router also supports data components, which are components that fetch and manage data for a specific route. These components offer a declarative and reusable approach to handling data fetching within routes.
To create a data component, you can define a component that fetches and manages data, and then pass it as the data
prop to the Route
component.
This function is then passed to the data
prop of the Route
component, initiating the data fetching in parallel with the page load.
In doing this, the data is available as soon as possible, reducing any delays that people may experience.
Once the data component is set up, the fetched data can be accessed within the route component by using the useRouteData
hook.
This utility allows you to retrieve the results of the data
function once the route is loaded.
This data function receives an object as its argument, containing valuable route information, including:
Key | Type | Description |
---|---|---|
params | object | The route parameters (same value as calling useParams() inside the route component) |
location | { pathname, search, hash, query, state, key} | An object that you can use to get more information about the path (corresponds to useLocation()) |
navigate | (to: string, options?: NavigateOptions) => void | A function that you can call to navigate to a different route instead (corresponds to useNavigate()) |
data | unknown | The data returned by the parent's data function, if any. (Data will pass through any intermediate nesting.) |
Organizing data functions
A possible way to use this is through exporting the data function of the corresponding route into a dedicated route.data.js
or route.data.ts
file.
This imports the data functions independently, without loading any additional resources.
Using this pattern means there is no need to import the fetchUser
function directly in the route component since it will be encapsulated within the [id].data.js
file.
Hash-based routing mode
The default behaviour in Solid Router is to use location.pathname
to find the route path.
However, there is more flexibility built into the router which gives you the option to easily switch to hash mode through the source
property in the <Router>
component.
This adjustment tells your application to use the URL hash to manage routes, which can be useful for ensuring compatability with browsers that do not support the History API or for serving static files.
Config-based routing
Defining routes in Solid does not always require the use of JSX.
An alternative approach is to use a configuration object to define your routes.
This method is helpful when you aim to define your routes in a separate file, import them into your app, and then pass them to the useRoutes
function.
In this example, the routes
config object contains the definitions for various routes and their respective components.
The useRoutes
function then takes the configuration object and generates the corresponding routes for the application.
Solid Route primitives
Solid Router offers a variety of primitives that interact with the Router and Route context. These primitives provide functionalities such as retrieving route parameters, navigating between routes, and accessing location information.
useParams
The useParams
primitive retrieves a reactive object containing the current route path paramteres as defined in the Route.
useNavigate
useNavigate
provides a method for imperative navigation.
It returns a navigate
function that accepts a path and an optional options object, allowing for customized navigation behavior.
The available options include:
resolve
(boolean, defaulttrue
): Resolve the path against the current route.replace
(boolean, defaultfalse
): Replace the history entry.scroll
(boolean, defaulttrue
): Scroll to top after navigation.state
(any, defaultundefined
): Pass custom state tolocation.state
.
The state is serialized using the structured clone algorithm, which does not support all object types.
useLocation
useLocation
retrieves a reactive location object, which is useful for accessing properties like pathname
, search
, hash
, state
, etc.
useSearchParams
useSearchParams
returns a destructured array that contains a reactive object to read the current location's query parameters and a method to update them.
The setter method merges the entries into the current query string, and updates behave like a navigation.
useIsRouting
useIsRouting
retrieves a signal indicating whether the route is currently in a Transition.
This is useful for displaying stale/pending states during concurrent rendering.
useRouteData
useRouteData
retrieves the return value from the data function.
useMatch
useMatch
creates a Memo that returns match information if the current path matches the provided path, which is useful for determining if a given path matches the current route.
useRoutes
useRoutes
is used to define routes via a config object instead of JSX.
See Config-Based Routing for more details.
useBeforeLeave
useBeforeLeave
takes a function that will be called prior to leaving a route, providing various parameters and methods to manage route changes.
Access to more comprehensive insights and details on Solid Router can be accessed through its GitHub repository.