@solidjs/router
Advanced tools
Comparing version 0.10.1 to 0.10.2
@@ -562,2 +562,8 @@ import { isServer, getRequestEvent, createComponent as createComponent$1, delegateEvents, spread, mergeProps as mergeProps$1, template } from 'solid-js/web'; | ||
const path = createMemo(() => match().path); | ||
component && component.preload && component.preload(); | ||
const data = load ? load({ | ||
params, | ||
location, | ||
intent: intent || "initial" | ||
}) : undefined; | ||
const route = { | ||
@@ -571,2 +577,3 @@ parent, | ||
location, | ||
data, | ||
get children() { | ||
@@ -580,8 +587,2 @@ return outlet(); | ||
}; | ||
component && component.preload && component.preload(); | ||
load && load({ | ||
params, | ||
location, | ||
intent: intent || "initial" | ||
}); | ||
return route; | ||
@@ -588,0 +589,0 @@ } |
import type { Component, JSX } from "solid-js"; | ||
import type { MatchFilters, RouteLoadFunc, RouterIntegration, RouteSectionProps } from "../types"; | ||
import type { MatchFilters, RouteLoadFunc, RouteDefinition, RouterIntegration, RouteSectionProps } from "../types"; | ||
export type BaseRouterProps = { | ||
base?: string; | ||
root?: Component<RouteSectionProps>; | ||
children?: JSX.Element; | ||
children?: JSX.Element | RouteDefinition | RouteDefinition[]; | ||
}; | ||
@@ -8,0 +8,0 @@ export declare const createRouterComponent: (router: RouterIntegration) => (props: BaseRouterProps) => JSX.Element; |
@@ -353,2 +353,6 @@ import { createComponent, createContext, createMemo, createRenderEffect, createSignal, on, onCleanup, untrack, useContext, startTransition, resetErrorBoundaries } from "solid-js"; | ||
const path = createMemo(() => match().path); | ||
component && | ||
component.preload && | ||
component.preload(); | ||
const data = load ? load({ params, location, intent: intent || "initial" }) : undefined; | ||
const route = { | ||
@@ -363,2 +367,3 @@ parent, | ||
location, | ||
data, | ||
get children() { | ||
@@ -373,7 +378,3 @@ return outlet(); | ||
}; | ||
component && | ||
component.preload && | ||
component.preload(); | ||
load && load({ params, location, intent: intent || "initial" }); | ||
return route; | ||
} |
@@ -50,14 +50,15 @@ import type { Component, JSX, Signal } from "solid-js"; | ||
} | ||
export type RouteLoadFunc = (args: RouteLoadFuncArgs) => void; | ||
export interface RouteSectionProps { | ||
export type RouteLoadFunc<T = unknown> = (args: RouteLoadFuncArgs) => T; | ||
export interface RouteSectionProps<T = unknown> { | ||
params: Params; | ||
location: Location; | ||
data?: T; | ||
children?: JSX.Element; | ||
} | ||
export type RouteDefinition<S extends string | string[] = any> = { | ||
export type RouteDefinition<S extends string | string[] = any, T = unknown> = { | ||
path?: S; | ||
matchFilters?: MatchFilters<S>; | ||
load?: RouteLoadFunc; | ||
load?: RouteLoadFunc<T>; | ||
children?: RouteDefinition | RouteDefinition[]; | ||
component?: Component<RouteSectionProps>; | ||
component?: Component<RouteSectionProps<T>>; | ||
}; | ||
@@ -64,0 +65,0 @@ export type MatchFilter = readonly string[] | RegExp | ((s: string) => boolean); |
@@ -9,3 +9,3 @@ { | ||
"license": "MIT", | ||
"version": "0.10.1", | ||
"version": "0.10.2", | ||
"homepage": "https://github.com/solidjs/solid-router#readme", | ||
@@ -12,0 +12,0 @@ "repository": { |
169
README.md
@@ -353,4 +353,49 @@ <p> | ||
## Load Functions | ||
Even with smart caches it is possible that we have waterfalls both with view logic and with lazy loaded code. With load functions, we can instead start fetching the data parallel to loading the route, so we can use the data as soon as possible. The load function is called when the Route is loaded or eagerly when links are hovered. | ||
As its only argument, the load function is passed an object that you can use to access route information: | ||
```js | ||
import { lazy } from "solid-js"; | ||
import { Route } from "@solidjs/router"; | ||
const User = lazy(() => import("./pages/users/[id].js")); | ||
// load function | ||
function loadUser({params, location}) { | ||
// do loading | ||
} | ||
// Pass it in the route definition | ||
<Route path="/users/:id" component={User} load={loadUser} />; | ||
``` | ||
| 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()`](#uselocation)) | | ||
| intent | `"initial", "navigate", "native", "preload"` | Indicates why this function is being called. <ul><li>"initial" - the route is being initially shown (ie page load)</li><li>"native" - navigate originated from the browser (eg back/forward)</li><li>"navigate" - navigate originated from the router (eg call to navigate or anchor clicked)</li><li>"preload" - not navigating, just preloading (eg link hover)</li></ul> | | ||
A common pattern is to export the load function and data wrappers that corresponds to a route in a dedicated `route.data.js` file. This way, the data function can be imported without loading anything else. | ||
```js | ||
import { lazy } from "solid-js"; | ||
import { Route } from "@solidjs/router"; | ||
import loadUser from "./pages/users/[id].data.js"; | ||
const User = lazy(() => import("/pages/users/[id].js")); | ||
// In the Route definition | ||
<Route path="/users/:id" component={User} load={loadUser} />; | ||
``` | ||
The return value of the `load` function is passed to the page component when called at anytime other than `"preload"`, so you can initialize things in there, or alternatively use our new Data APIs: | ||
## Data APIs | ||
Keep in mind these are completely optional. To use but showcase the power of our load mechanism. | ||
### `cache` | ||
@@ -374,2 +419,32 @@ | ||
Using it with load function might look like: | ||
```js | ||
import { lazy } from "solid-js"; | ||
import { Route } from "@solidjs/router"; | ||
import { getUser } from ... // the cache function | ||
const User = lazy(() => import("./pages/users/[id].js")); | ||
// load function | ||
function loadUser({params, location}) { | ||
void getUser(params.id) | ||
} | ||
// Pass it in the route definition | ||
<Route path="/users/:id" component={User} load={loadUser} />; | ||
``` | ||
Inside your page component you: | ||
```jsx | ||
// pages/users/[id].js | ||
import { getUser } from ... // the cache function | ||
export default function User(props) { | ||
const user = createAsync(() => getUser(props.params.id)); | ||
return <h1>{user().name}</h1>; | ||
} | ||
``` | ||
Cached function has a few useful methods for getting the key that are useful for invalidation. | ||
@@ -428,3 +503,3 @@ ```ts | ||
<form action={deleteUser} method="post"> | ||
<form action={deleteTodo} method="post"> | ||
<input type="hidden" name="id" value={todo.id} /> | ||
@@ -436,5 +511,5 @@ <button type="submit">Delete</button> | ||
```js | ||
const deleteUser = action(api.deleteUser) | ||
const deleteUser = action(api.deleteTodo) | ||
<form action={deleteUser.with(todo.id)} method="post"> | ||
<form action={deleteTodo.with(todo.id)} method="post"> | ||
<button type="submit">Delete</button> | ||
@@ -511,55 +586,2 @@ </form> | ||
### Load Functions | ||
Even with the cache API it is possible that we have waterfalls both with view logic and with lazy loaded code. With load functions, we can instead start fetching the data parallel to loading the route, so we can use the data as soon as possible. | ||
To do this, we can call our cache function in the load function. | ||
```js | ||
import { lazy } from "solid-js"; | ||
import { Route } from "@solidjs/router"; | ||
import { getUser } from ... // the cache function | ||
const User = lazy(() => import("./pages/users/[id].js")); | ||
// load function | ||
function loadUser({params, location}) { | ||
void getUser(params.id) | ||
} | ||
// Pass it in the route definition | ||
<Route path="/users/:id" component={User} load={loadUser} />; | ||
``` | ||
The load function is called when the Route is loaded or eagerly when links are hovered. Inside your page component you: | ||
```jsx | ||
// pages/users/[id].js | ||
import { getUser } from ... // the cache function | ||
export default function User(props) { | ||
const user = createAsync(() => getUser(props.params.id)); | ||
return <h1>{user().name}</h1>; | ||
} | ||
``` | ||
As its only argument, the load function is passed an object that you can use to access route information: | ||
| 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()`](#uselocation)) | | ||
A common pattern is to export the preload function and data wrappers that corresponds to a route in a dedicated `route.data.js` file. This way, the data function can be imported without loading anything else. | ||
```js | ||
import { lazy } from "solid-js"; | ||
import { Route } from "@solidjs/router"; | ||
import loadUser from "./pages/users/[id].data.js"; | ||
const User = lazy(() => import("/pages/users/[id].js")); | ||
// In the Route definition | ||
<Route path="/users/:id" component={User} load={loadUser} />; | ||
``` | ||
## Config Based Routing | ||
@@ -842,2 +864,37 @@ | ||
That being said you can reproduce the old pattern largely by turning off preloads at the router level and then injecting your own Context: | ||
```js | ||
import { lazy } from "solid-js"; | ||
import { Route } from "@solidjs/router"; | ||
const User = lazy(() => import("./pages/users/[id].js")); | ||
// load function | ||
function loadUser({params, location}) { | ||
const [user] = createResource(() => params.id, fetchUser); | ||
return user; | ||
} | ||
// Pass it in the route definition | ||
<Router preload={false}> | ||
<Route path="/users/:id" component={User} load={loadUser} /> | ||
</Router> | ||
``` | ||
And then in your component taking the page props and putting them in a Context. | ||
```js | ||
function User(props) { | ||
<UserContext.Provider value={props.data}> | ||
{/* my component content */} | ||
</UserContext.Provider> | ||
} | ||
// Somewhere else | ||
function UserDetails() { | ||
const user = useContext(UserContext) | ||
// render stuff | ||
} | ||
``` | ||
## SPAs in Deployed Environments | ||
@@ -844,0 +901,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
145947
3211
916