Route
<Route>
renders a route configuration object to be used by the <Routes>
component.
tsx
<Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/students" | "/students"[]
="/students" component(property) component: Component<{}>
={Studentsfunction Students(): JSX.Element
} />
tsx
<Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/students" | "/students"[]
="/students" component(property) component: Component<{}>
={Studentsfunction Students(): JSX.Element
} />
Usage
The <Route>
component allows the manual registration of routes when added as children to the <Routes>
component. It is a re-export from @solidjs/router
. If only using file system routing you probably will not need any of the information on this page. But it can serve as a reference to how this works under the hood.
root.tsx
tsx
import { Routes(alias) const Routes: (props: RoutesProps) => JSX.Element
import Routes
, Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
} from "solid-start";
import Home(alias) function Home(): JSX.Element
import Home
from "./pages/Home"; import Users(alias) function Users(): JSX.Element
import Users
from "./pages/Users";
export default function RootLayoutfunction RootLayout(): JSX.Element
() { return (
<>
<h1(property) JSX.HTMLElementTags.h1: JSX.HTMLAttributes<HTMLHeadingElement>
>My Site with Lots of Pages</h1(property) JSX.HTMLElementTags.h1: JSX.HTMLAttributes<HTMLHeadingElement>
> <Routes(alias) const Routes: (props: RoutesProps) => JSX.Element
import Routes
> <Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/" | "/"[]
="/" component(property) component: Component<{}>
={Home(alias) function Home(): JSX.Element
import Home
} /> <Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/users" | "/users"[]
="/users" component(property) component: Component<{}>
={Users(alias) function Users(): JSX.Element
import Users
} /> <Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/about" | "/about"[]
="/about" element(property) element?: JSX.Element
={<div(property) JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>
>This site was made with Solid</div(property) JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>
>} /> </Routes(alias) const Routes: (props: RoutesProps) => JSX.Element
import Routes
> </>
);
}
root.tsx
tsx
import { Routes(alias) const Routes: (props: RoutesProps) => JSX.Element
import Routes
, Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
} from "solid-start";
import Home(alias) function Home(): JSX.Element
import Home
from "./pages/Home"; import Users(alias) function Users(): JSX.Element
import Users
from "./pages/Users";
export default function RootLayoutfunction RootLayout(): JSX.Element
() { return (
<>
<h1(property) JSX.HTMLElementTags.h1: JSX.HTMLAttributes<HTMLHeadingElement>
>My Site with Lots of Pages</h1(property) JSX.HTMLElementTags.h1: JSX.HTMLAttributes<HTMLHeadingElement>
> <Routes(alias) const Routes: (props: RoutesProps) => JSX.Element
import Routes
> <Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/" | "/"[]
="/" component(property) component: Component<{}>
={Home(alias) function Home(): JSX.Element
import Home
} /> <Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/users" | "/users"[]
="/users" component(property) component: Component<{}>
={Users(alias) function Users(): JSX.Element
import Users
} /> <Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/about" | "/about"[]
="/about" element(property) element?: JSX.Element
={<div(property) JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>
>This site was made with Solid</div(property) JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>
>} /> </Routes(alias) const Routes: (props: RoutesProps) => JSX.Element
import Routes
> </>
);
}
Reference
<Route>
Render <Route>
components as children of the <Routes>
component to define your own routes, even alongside the file system routes. They are merged together by the <Routes>
component.
Props
Prop |
Type |
Description |
path |
string |
The path segment for this portion of the route. |
component |
function |
A component definition to be instantiated on route match. Only one of `element` or `component` should be present. |
element |
unknown |
The element defines an expression that is run when the route is matched. Generally this is an instantiated component. Only one of `element` or `component` should be present. |
data |
function |
Method for registering data loading functions that run in parallel on route match. |
Dynamic Routes
If you don't know the path ahead of time, you might want to treat part of the path as a flexible parameter that is passed on to the component.
root.tsx
tsx
import { lazy(alias) function lazy<T extends Component<any>>(fn: () => Promise<{
default: T;
}>): T & {
preload: () => Promise<{
default: T;
}>;
}
import lazy
} from "solid-js"; import { Routes(alias) const Routes: (props: RoutesProps) => JSX.Element
import Routes
, Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
} from "solid-start"
const Usersconst Users: (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
= lazy(alias) lazy<() => JSX.Element>(fn: () => Promise<{
default: () => JSX.Element;
}>): (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
import lazy
(() => import("./pages/Users")); const Userconst User: (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
= lazy(alias) lazy<() => JSX.Element>(fn: () => Promise<{
default: () => JSX.Element;
}>): (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
import lazy
(() => import("./pages/User")); const Homeconst Home: (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
= lazy(alias) lazy<() => JSX.Element>(fn: () => Promise<{
default: () => JSX.Element;
}>): (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
import lazy
(() => import("./pages/Home"));
export default function RootLayoutfunction RootLayout(): JSX.Element
() { return <>
<h1(property) JSX.HTMLElementTags.h1: JSX.HTMLAttributes<HTMLHeadingElement>
>My Site with Lots of Pages</h1(property) JSX.HTMLElementTags.h1: JSX.HTMLAttributes<HTMLHeadingElement>
> <Routes(alias) const Routes: (props: RoutesProps) => JSX.Element
import Routes
> <Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/users" | "/users"[]
="/users" component(property) component: Component<{}>
={Usersconst Users: (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
} /> <Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/users/:id" | "/users/:id"[]
="/users/:id" component(property) component: Component<{}>
={Userconst User: (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
} /> <Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/" | "/"[]
="/" component(property) component: Component<{}>
={Homeconst Home: (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
} /> <Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/about" | "/about"[]
="/about" element(property) element?: JSX.Element
={<div(property) JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>
>This site was made with Solid</div(property) JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>
>} /> </Routes(alias) const Routes: (props: RoutesProps) => JSX.Element
import Routes
> </>
}
root.tsx
tsx
import { lazy(alias) function lazy<T extends Component<any>>(fn: () => Promise<{
default: T;
}>): T & {
preload: () => Promise<{
default: T;
}>;
}
import lazy
} from "solid-js"; import { Routes(alias) const Routes: (props: RoutesProps) => JSX.Element
import Routes
, Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
} from "solid-start"
const Usersconst Users: (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
= lazy(alias) lazy<() => JSX.Element>(fn: () => Promise<{
default: () => JSX.Element;
}>): (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
import lazy
(() => import("./pages/Users")); const Userconst User: (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
= lazy(alias) lazy<() => JSX.Element>(fn: () => Promise<{
default: () => JSX.Element;
}>): (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
import lazy
(() => import("./pages/User")); const Homeconst Home: (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
= lazy(alias) lazy<() => JSX.Element>(fn: () => Promise<{
default: () => JSX.Element;
}>): (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
import lazy
(() => import("./pages/Home"));
export default function RootLayoutfunction RootLayout(): JSX.Element
() { return <>
<h1(property) JSX.HTMLElementTags.h1: JSX.HTMLAttributes<HTMLHeadingElement>
>My Site with Lots of Pages</h1(property) JSX.HTMLElementTags.h1: JSX.HTMLAttributes<HTMLHeadingElement>
> <Routes(alias) const Routes: (props: RoutesProps) => JSX.Element
import Routes
> <Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/users" | "/users"[]
="/users" component(property) component: Component<{}>
={Usersconst Users: (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
} /> <Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/users/:id" | "/users/:id"[]
="/users/:id" component(property) component: Component<{}>
={Userconst User: (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
} /> <Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/" | "/"[]
="/" component(property) component: Component<{}>
={Homeconst Home: (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
} /> <Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/about" | "/about"[]
="/about" element(property) element?: JSX.Element
={<div(property) JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>
>This site was made with Solid</div(property) JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>
>} /> </Routes(alias) const Routes: (props: RoutesProps) => JSX.Element
import Routes
> </>
}
The colon indicates that id
can be any string, and as long as the URL fits that pattern, the User
component will show.
You can then access that id
from within a route component with useParams
:
jsx
import { A(alias) const A: (props: AnchorProps) => JSX.Element
import A
, useParams(alias) const useParams: <T extends Params>() => T
import useParams
} from "solid-start"; import { createResourceCreates a resource that wraps a repeated promise in a reactive pattern:
```typescript
// Without source
const [resource, { mutate, refetch }] = createResource(fetcher, options);
// With source
const [resource, { mutate, refetch }] = createResource(source, fetcher, options);
```
(alias) function createResource<T, R = unknown>(fetcher: ResourceFetcher<true, T, R>, options: InitializedResourceOptions<NoInfer<T>, true>): InitializedResourceReturn<T, R> (+3 overloads)
import createResource
} from "solid-js";
export default function Userfunction User(): JSX.Element
() { const params = useParams(alias) useParams<Params>(): Params
import useParams
(); const [userDataconst userData: Resource<{
id: any;
name: string;
}>
] = createResourceCreates a resource that wraps a repeated promise in a reactive pattern:
```typescript
// Without source
const [resource, { mutate, refetch }] = createResource(fetcher, options);
// With source
const [resource, { mutate, refetch }] = createResource(source, fetcher, options);
```
(alias) createResource<{
id: any;
name: string;
}, string, unknown>(source: ResourceSource<string>, fetcher: ResourceFetcher<string, {
id: any;
name: string;
}, unknown>, options?: ResourceOptions<{
id: any;
name: string;
}, string> | undefined): ResourceReturn<...> (+3 overloads)
import createResource
(() => params.id, fetchUserlet fetchUser: (id: any) => {
id: any;
name: string;
}
); return <A(alias) const A: (props: AnchorProps) => JSX.Element
import A
href(property) AnchorProps.href: string
={userDataconst userData: Resource<{
id: any;
name: string;
}>
.twitter}>{userDataconst userData: Resource<{
id: any;
name: string;
}>
.nameReturns the name of the function. Function names are read-only and can not be changed.
(property) Function.name: string
}</A(alias) const A: (props: AnchorProps) => JSX.Element
import A
> }
jsx
import { A(alias) const A: (props: AnchorProps) => JSX.Element
import A
, useParams(alias) const useParams: <T extends Params>() => T
import useParams
} from "solid-start"; import { createResourceCreates a resource that wraps a repeated promise in a reactive pattern:
```typescript
// Without source
const [resource, { mutate, refetch }] = createResource(fetcher, options);
// With source
const [resource, { mutate, refetch }] = createResource(source, fetcher, options);
```
(alias) function createResource<T, R = unknown>(fetcher: ResourceFetcher<true, T, R>, options: InitializedResourceOptions<NoInfer<T>, true>): InitializedResourceReturn<T, R> (+3 overloads)
import createResource
} from "solid-js";
export default function Userfunction User(): JSX.Element
() { const params = useParams(alias) useParams<Params>(): Params
import useParams
(); const [userDataconst userData: Resource<{
id: any;
name: string;
}>
] = createResourceCreates a resource that wraps a repeated promise in a reactive pattern:
```typescript
// Without source
const [resource, { mutate, refetch }] = createResource(fetcher, options);
// With source
const [resource, { mutate, refetch }] = createResource(source, fetcher, options);
```
(alias) createResource<{
id: any;
name: string;
}, string, unknown>(source: ResourceSource<string>, fetcher: ResourceFetcher<string, {
id: any;
name: string;
}, unknown>, options?: ResourceOptions<{
id: any;
name: string;
}, string> | undefined): ResourceReturn<...> (+3 overloads)
import createResource
(() => params.id, fetchUserlet fetchUser: (id: any) => {
id: any;
name: string;
}
); return <A(alias) const A: (props: AnchorProps) => JSX.Element
import A
href(property) AnchorProps.href: string
={userDataconst userData: Resource<{
id: any;
name: string;
}>
.twitter}>{userDataconst userData: Resource<{
id: any;
name: string;
}>
.nameReturns the name of the function. Function names are read-only and can not be changed.
(property) Function.name: string
}</A(alias) const A: (props: AnchorProps) => JSX.Element
import A
> }
Optional Parameters
Parameters can be specified as optional by adding a question mark to the end of the parameter name:
jsx
// Matches stories and stories/123 but not stories/123/comments
<Route path='/stories/:id?' element={<Stories/>} />
jsx
// Matches stories and stories/123 but not stories/123/comments
<Route path='/stories/:id?' element={<Stories/>} />
Wildcard Routes
:param
lets you match an arbitrary name at that point in the path. You can use *
to match any end of the path:
jsx
// Matches any path that begins with foo, including foo/, foo/a/, foo/a/b/c
<Route path='foo/*' component={Foo}/>
jsx
// Matches any path that begins with foo, including foo/, foo/a/, foo/a/b/c
<Route path='foo/*' component={Foo}/>
If you want to expose the wild part of the path to the component as a parameter, you can name it:
jsx
<Route path='foo/*any' element={<div>{useParams().any}</div>}/>
jsx
<Route path='foo/*any' element={<div>{useParams().any}</div>}/>
Note that the wildcard token must be the last part of the path; foo/*any/bar
won't create any routes.
Multiple Paths
Routes also support defining multiple paths using an array. This allows a route to remain mounted and not rerender when switching between two or more locations that it matches:
jsx
// Navigating from login to register does not cause the Login component to re-render
<Route path={["login", "register"]} component={Login}/>
jsx
// Navigating from login to register does not cause the Login component to re-render
<Route path={["login", "register"]} component={Login}/>
Route Data Functions
In the above example, the User component is lazy-loaded and then the data is fetched. With route data functions, we can instead start fetching the data in parallel to loading the route, so we can use the data as soon as possible.
To do this, create a function that fetches and returns the data using createResource
. Then pass that function to the data
prop of the Route
component.
root.tsx
tsx
// Route Data function
function studentDatafunction studentData({ params, location, navigate, data }: RouteDataArgs): Resource<any>
({ params(parameter) params: RouteParams<any>
, location(parameter) location: Location<unknown>
, navigate(parameter) navigate: Navigator
, data }: RouteDataArgs(alias) type RouteDataArgs<T extends "$" = "$"> = {
data: StartRoutes[T]["data"];
params: RouteParams<StartRoutes[T]["params"]>;
location: Location;
navigate: Navigator;
}
import RouteDataArgs
) { const [studentconst student: Resource<any>
] = createResourceCreates a resource that wraps a repeated promise in a reactive pattern:
```typescript
// Without source
const [resource, { mutate, refetch }] = createResource(fetcher, options);
// With source
const [resource, { mutate, refetch }] = createResource(source, fetcher, options);
```
(alias) createResource<any, string, unknown>(source: ResourceSource<string>, fetcher: ResourceFetcher<string, any, unknown>, options?: ResourceOptions<any, string> | undefined): ResourceReturn<...> (+3 overloads)
import createResource
(() => params(parameter) params: RouteParams<any>
.id, fetchStudent(alias) function fetchStudent(id: string): Promise<any>
import fetchStudent
); return studentconst student: Resource<any>
; }
// Pass it in the route definition
<Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/students/:id" | "/students/:id"[]
="/students/:id" component(property) component: Component<{}>
={StudentProfileconst StudentProfile: (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
} data(property) data?: RouteDataFunc<unknown, unknown> | undefined
={studentDatafunction studentData({ params, location, navigate, data }: RouteDataArgs): Resource<any>
} />;
root.tsx
tsx
// Route Data function
function studentDatafunction studentData({ params, location, navigate, data }: RouteDataArgs): Resource<any>
({ params(parameter) params: RouteParams<any>
, location(parameter) location: Location<unknown>
, navigate(parameter) navigate: Navigator
, data }: RouteDataArgs(alias) type RouteDataArgs<T extends "$" = "$"> = {
data: StartRoutes[T]["data"];
params: RouteParams<StartRoutes[T]["params"]>;
location: Location;
navigate: Navigator;
}
import RouteDataArgs
) { const [studentconst student: Resource<any>
] = createResourceCreates a resource that wraps a repeated promise in a reactive pattern:
```typescript
// Without source
const [resource, { mutate, refetch }] = createResource(fetcher, options);
// With source
const [resource, { mutate, refetch }] = createResource(source, fetcher, options);
```
(alias) createResource<any, string, unknown>(source: ResourceSource<string>, fetcher: ResourceFetcher<string, any, unknown>, options?: ResourceOptions<any, string> | undefined): ResourceReturn<...> (+3 overloads)
import createResource
(() => params(parameter) params: RouteParams<any>
.id, fetchStudent(alias) function fetchStudent(id: string): Promise<any>
import fetchStudent
); return studentconst student: Resource<any>
; }
// Pass it in the route definition
<Route(alias) const Route: <S extends string>(props: RouteProps<S>) => JSX.Element
import Route
path(property) path: "/students/:id" | "/students/:id"[]
="/students/:id" component(property) component: Component<{}>
={StudentProfileconst StudentProfile: (() => JSX.Element) & {
preload: () => Promise<{
default: () => JSX.Element;
}>;
}
} data(property) data?: RouteDataFunc<unknown, unknown> | undefined
={studentDatafunction studentData({ params, location, navigate, data }: RouteDataArgs): Resource<any>
} />;
When the route is loaded, the data function is called, and the result can be accessed by calling useRouteData()
in the route component.
pages/students/[id].tsx
tsx
import { useRouteData(alias) function useRouteData<T extends "$">(): ReturnType<StartRoutes[T]["data"]> (+1 overload)
import useRouteData
} from 'solid-start';
export default function StudentProfilefunction StudentProfile(): JSX.Element
() { const studentconst student: Resource<Student>
= useRouteData(alias) useRouteData<({ params, location, navigate, data }: RouteDataArgs<"$">) => Resource<Student>>(): Resource<Student> (+1 overload)
import useRouteData
<typeof studentDatafunction studentData({ params, location, navigate, data }: RouteDataArgs<"$">): Resource<Student>
>(); return <h1(property) JSX.HTMLElementTags.h1: JSX.HTMLAttributes<HTMLHeadingElement>
>{studentconst student: () => Student | undefined
()?.name(property) name: string | undefined
}</h1(property) JSX.HTMLElementTags.h1: JSX.HTMLAttributes<HTMLHeadingElement>
>; }
pages/students/[id].tsx
tsx
import { useRouteData(alias) function useRouteData<T extends "$">(): ReturnType<StartRoutes[T]["data"]> (+1 overload)
import useRouteData
} from 'solid-start';
export default function StudentProfilefunction StudentProfile(): JSX.Element
() { const studentconst student: Resource<Student>
= useRouteData(alias) useRouteData<({ params, location, navigate, data }: RouteDataArgs<"$">) => Resource<Student>>(): Resource<Student> (+1 overload)
import useRouteData
<typeof studentDatafunction studentData({ params, location, navigate, data }: RouteDataArgs<"$">): Resource<Student>
>(); return <h1(property) JSX.HTMLElementTags.h1: JSX.HTMLAttributes<HTMLHeadingElement>
>{studentconst student: () => Student | undefined
()?.name(property) name: string | undefined
}</h1(property) JSX.HTMLElementTags.h1: JSX.HTMLAttributes<HTMLHeadingElement>
>; }
Nested Routes
The following two route definitions have the same result:
jsx
<Route path="/users/:id" component={User} />
jsx
<Route path="/users/:id" component={User} />
jsx
<Route path="/users">
<Route path="/:id" component={User} />
</Route>
jsx
<Route path="/users">
<Route path="/:id" component={User} />
</Route>
/users/:id
renders the <User/>
component, and /users/
is an empty route. Only leaf Route nodes (innermost Route
components) are given a route.
If you want to make the parent its own route, you have to specify it separately. So, if you want to render a page with <Users>
for /users
and <User>
for /users/:id
, you need to specify both as leaf routes:
jsx
// This is not a leaf route, its actually a parent layout route
<Route path="/users" component={Users}>
<Route path="/:id" component={User} />
</Route>
jsx
// This is not a leaf route, its actually a parent layout route
<Route path="/users" component={Users}>
<Route path="/:id" component={User} />
</Route>
jsx
<Route path="/users" component={Users} />
<Route path="/users/:id" component={User} />
jsx
<Route path="/users" component={Users} />
<Route path="/users/:id" component={User} />
jsx
<Route path="/users">
<Route path="/" component={Users} />
<Route path="/:id" component={User} />
</Route>
jsx
<Route path="/users">
<Route path="/" component={Users} />
<Route path="/:id" component={User} />
</Route>