How to use load property of <Route>

I haven't been able to figure out how to use <Route>'s load function and haven't found a complete example. One property of props in Person has the data from the fetch but it is still a promise. I'm not sure if it should be and if so, what to do with it. index.jsx
import { lazy } from "solid-js";
import { render } from "solid-js/web";
import { Router, Route } from "@solidjs/router";
import { loadPerson } from "./route.data";

const Person = lazy(() => import("./pages/Person"))
const Home = lazy(() => import("./pages/Home"))

render(() => (
<Router>
<Route path="/" component={Home} />
<Route
path="/person"
load={loadPerson}
component={Person}
/>

</Router>
), document.getElementById("root"));
import { lazy } from "solid-js";
import { render } from "solid-js/web";
import { Router, Route } from "@solidjs/router";
import { loadPerson } from "./route.data";

const Person = lazy(() => import("./pages/Person"))
const Home = lazy(() => import("./pages/Home"))

render(() => (
<Router>
<Route path="/" component={Home} />
<Route
path="/person"
load={loadPerson}
component={Person}
/>

</Router>
), document.getElementById("root"));
route.data.js
import { cache } from "@solidjs/router";

async function fetchPerson() {
const a = await fetch(`https://swapi.tech/api/people/1/`);
const b = await a.json();
console.log("b", b);
return b;
}

export const loadPerson = cache(async () => {
const [person] = createResource(() => "", fetchPerson);
return person;
}, "getUserKey");
import { cache } from "@solidjs/router";

async function fetchPerson() {
const a = await fetch(`https://swapi.tech/api/people/1/`);
const b = await a.json();
console.log("b", b);
return b;
}

export const loadPerson = cache(async () => {
const [person] = createResource(() => "", fetchPerson);
return person;
}, "getUserKey");
Person.jsx
import { createSignal, createResource } from "solid-js";

export default function Person(props) {
// do I use createResource again?
const [user] = createResource("", peops.data); // doesn't work

return (
<>
<input
type="number"
min="1"
placeholder="Enter Numeric Id"
onInput={(e) => setUserId(e.currentTarget.value)}
/>
<span>{user.loading && "Loading..."}</span>
<div>
<pre>{JSON.stringify(user(), null, 2)}</pre>
</div>
</>
);
};
import { createSignal, createResource } from "solid-js";

export default function Person(props) {
// do I use createResource again?
const [user] = createResource("", peops.data); // doesn't work

return (
<>
<input
type="number"
min="1"
placeholder="Enter Numeric Id"
onInput={(e) => setUserId(e.currentTarget.value)}
/>
<span>{user.loading && "Loading..."}</span>
<div>
<pre>{JSON.stringify(user(), null, 2)}</pre>
</div>
</>
);
};
11 Replies
Carl (klequis)
Carl (klequis)OP9mo ago
This works but const person = createAsync(() => getPerson(props.params.id)); in Person seems to be redundant. Is it correct?
import { lazy } from "solid-js";
import { render } from "solid-js/web";
import { Router, Route, createAsync } from "@solidjs/router";
import { cache } from "@solidjs/router";

const getPerson = cache(async (id) => {
return (await fetch(`https://swapi.tech/api/people/${id}/`)).json()
}, "getPerson")

const Home = lazy(() => import("./pages/Home"))

function loadPerson({params, location}) {
void getPerson(params.id)
}

render(() => (
<Router>
<Route path="/" component={Home} />
<Route
path="/person/:id"
component={Person}
load={loadPerson}
/>
</Router>
), document.getElementById("root"));

function Person(props) {
const person = createAsync(() => getPerson(props.params.id));

return (
<>
<h1>Person</h1>
<div>
<pre>{JSON.stringify(person(), null, 2)}</pre>
</div>
</>
)
}
import { lazy } from "solid-js";
import { render } from "solid-js/web";
import { Router, Route, createAsync } from "@solidjs/router";
import { cache } from "@solidjs/router";

const getPerson = cache(async (id) => {
return (await fetch(`https://swapi.tech/api/people/${id}/`)).json()
}, "getPerson")

const Home = lazy(() => import("./pages/Home"))

function loadPerson({params, location}) {
void getPerson(params.id)
}

render(() => (
<Router>
<Route path="/" component={Home} />
<Route
path="/person/:id"
component={Person}
load={loadPerson}
/>
</Router>
), document.getElementById("root"));

function Person(props) {
const person = createAsync(() => getPerson(props.params.id));

return (
<>
<h1>Person</h1>
<div>
<pre>{JSON.stringify(person(), null, 2)}</pre>
</div>
</>
)
}
peerreynders
peerreynders9mo ago
This reflects my understanding. The return type of cache() is identical to the return type of the wrapped function; so it will return a promise (i.e. is async) if the wrapped function returns one. createAsync() converts a promise (async) to a signal (i.e. it creates an async-to-reactive boundary). The resulting signal can then be used in JSX and be expected to reactively update. This is handy when you revalidate, as the wrapped function is re-run to produce an entirely new promise that once resolved has its value placed on the signal created by createAsync(). https://docs.solidjs.com/reference/solid-router/data-apis/cache#:~:text=The%20cache%20can,from%20the%20actions.
Carl (klequis)
Carl (klequis)OP9mo ago
Helps improve my understanding. Thanks!
peerreynders
peerreynders9mo ago
1. The “documentation” you were looking for was here https://github.com/solidjs/solid-router?tab=readme-ov-file#data-functions--useroutedata 2. Based on your code I put together a working StackBlitz example: https://stackblitz.com/edit/solidjs-templates-h7n8dj 3. The Data API (cache/createAsync) is considered an alternative to "Load Functions" https://github.com/solidjs/solid-router?tab=readme-ov-file#data-apis 4. Use either createResource OR cache/createAsync BUT not both. cache cannot be used on createResource. Come SolidJS 2.0 cache/createAsync will be the preferred approach. createResource turned out to be not primitive enough so it was broken into cache() and createAsync()
peerreynders
StackBlitz
solidjs/router old Load Functions API demo - StackBlitz
A Solid TypeScript project based on @solidjs/router, solid-js, typescript, vite and vite-plugin-solid
GitHub
GitHub - solidjs/solid-router: A universal router for Solid inspire...
A universal router for Solid inspired by Ember and React Router - solidjs/solid-router
peerreynders
peerreynders9mo ago
Same demo; this time with cache/createAsync instead https://stackblitz.com/edit/solidjs-templates-vgam8k
peerreynders
StackBlitz
solidjs/router new Data API demo - StackBlitz
A Solid TypeScript project based on @solidjs/router, solid-js, typescript, vite and vite-plugin-solid
Carl (klequis)
Carl (klequis)OP9mo ago
I have since created two examples. I couldn't get them working on StackBlitz so here they are in github: https://github.com/klequis/solid-router-load-functions I find your first example (solidjs-templates-h7n8dj) interesting in the way it differs from my example02 in the above repo. You - modified the response in fetchPerson returning only name, - then use createResource in loadPerson. - but don't need createAsync in <Person> I did neither but did need createAsync in [id].jsx (formally Person.jsx).
I also followed "A common pattern" example from this section of the router README Thank you for your efforts. They have been very educational. I just noticed that your solution using createResource in the load function is listed in the Migration from v0.9.x doc and it suggests that was the way to do it before 10.x
peerreynders
peerreynders9mo ago
The pattern in SolidJS 2.0 is moving towards bypassing the Route load property entirely, relying entirely on cache() to dedup requests.
Carl (klequis)
Carl (klequis)OP9mo ago
I was searching far and wide for examples of using the load function and found next to nothing. Perhaps it was never very popular.
peerreynders
peerreynders9mo ago
useRouteData has been a thing with SolidStart Beta 1, but the thinking has changed drastically with Beta 2. https://hackmd.io/@0u1u3zEAQAO0iYWVAStEvw/rkRVTcTWp
HackMD
Router Data APIs - HackMD
Potential Router APIs for data
Carlo Nyte
Carlo Nyte9mo ago
Thank you for this! And thank you @klequis for asking the question, I'm currently struggling with this and didn't know the correct way to ask it. @peerreynders sorry if this is obvious, but is the advantage of using the cache function is that it actually caches the data so that if the user goes back to the page/ component again there won't be another request made to the server?
peerreynders
peerreynders9mo ago
The intent of the cache is to short circuit duplicate fetches when multiple components on the same route run the same “server function”. By going through the function wrapped in cache only a single fetch is issued and the components can share the processed response. That cached processed response is intended to expire once the route has finished loading so it has an extremely short “maxAge” (the cache timeout seems to be 180 secs). I haven't used it in this way yet but the code seems to suggest that createAsync will reactively receive the most recent value if cache reruns the function/fetch due to a revalidate invalidation.
GitHub
solid-router/src/data/cache.ts at d1a8aab5a3ebfb65726f1aabec80dd42a...
A universal router for Solid inspired by Ember and React Router - solidjs/solid-router
Want results from more Discord servers?
Add your server