S
SolidJS6mo ago
ali

How to make fetch request on server before sending html to client?

Hello everyone, I have a question about fetching data. I want to fetch data from an api and send html based on what I fetch.
import { createResource } from "solid-js";

const fetchData = async () => {
"use server";
const response = await fetch(
"http://localhost:5000/api/items?" +
new URLSearchParams({
type: "11",
min: "0",
max: "1000000",
polygon:
"29.00743125000136 59.284420699563725, 13.36290000000119 59.284420699563725, -2.2816312499989806 59.284420699563725, -2.2816312499989806 32.5773969429995, 13.36290000000119 32.5773969429995, 29.00743125000136 32.5773969429995, 29.00743125000136 59.284420699563725",
polygon2: "",
itemSort: "new",
})
);
const res = await response.json();
console.log(res);
return res;
};

export default function Home() {
const data = createResource(fetchData);
console.log(data);

return <main>{data.toString()}</main>;
}
import { createResource } from "solid-js";

const fetchData = async () => {
"use server";
const response = await fetch(
"http://localhost:5000/api/items?" +
new URLSearchParams({
type: "11",
min: "0",
max: "1000000",
polygon:
"29.00743125000136 59.284420699563725, 13.36290000000119 59.284420699563725, -2.2816312499989806 59.284420699563725, -2.2816312499989806 32.5773969429995, 13.36290000000119 32.5773969429995, 29.00743125000136 32.5773969429995, 29.00743125000136 59.284420699563725",
polygon2: "",
itemSort: "new",
})
);
const res = await response.json();
console.log(res);
return res;
};

export default function Home() {
const data = createResource(fetchData);
console.log(data);

return <main>{data.toString()}</main>;
}
The way I have it set up now results in the console.log(res); in the async fetchData function giving me the correct result, but the console.log(data); returns this:
[
[Function: read] { loading: true, error: undefined, state: 'pending' },
{ refetch: [Function: load], mutate: [Function: mutate] }
]
[
[Function: read] { loading: true, error: undefined, state: 'pending' },
{ refetch: [Function: load], mutate: [Function: mutate] }
]
Question: How do I make the sending of the html to the frontend wait until the async function has completed What I have tried: I have already tried to make the function Home() async. This resulted in the whole component not rendering. Help would be appreciated!
10 Replies
ali
aliOP6mo ago
Thanks for the reply. I have changed my code now to this:
import { createAsync, cache } from "@solidjs/router";

const getData = cache(async () => {
"use server";
const response = await fetch(
"http://localhost:5000/api/items?" +
new URLSearchParams({
type: "11",
min: "0",
max: "1000000",
polygon:
"29.00743125000136 59.284420699563725, 13.36290000000119 59.284420699563725, -2.2816312499989806 59.284420699563725, -2.2816312499989806 32.5773969429995, 13.36290000000119 32.5773969429995, 29.00743125000136 32.5773969429995, 29.00743125000136 59.284420699563725",
polygon2: "",
itemSort: "new",
})
);
const res = await response.json();
return res;
}, "users");

export const route = {
load: () => getData(),
};

export default function Home() {
const data = createAsync(() => getData());
return <main>{data()}</main>;
}
import { createAsync, cache } from "@solidjs/router";

const getData = cache(async () => {
"use server";
const response = await fetch(
"http://localhost:5000/api/items?" +
new URLSearchParams({
type: "11",
min: "0",
max: "1000000",
polygon:
"29.00743125000136 59.284420699563725, 13.36290000000119 59.284420699563725, -2.2816312499989806 59.284420699563725, -2.2816312499989806 32.5773969429995, 13.36290000000119 32.5773969429995, 29.00743125000136 32.5773969429995, 29.00743125000136 59.284420699563725",
polygon2: "",
itemSort: "new",
})
);
const res = await response.json();
return res;
}, "users");

export const route = {
load: () => getData(),
};

export default function Home() {
const data = createAsync(() => getData());
return <main>{data()}</main>;
}
but instead of getting the rows from the DB, in <main>{data()}</main> I get: "undefinedundefinedundefinedundefinedundefined" In the api, I limited the rows to be returned to 5. So it seems it is giving me the right amount of results, but they are all undefined. Do you know why?
mdynnl
mdynnl6mo ago
you could check the actual response of the api, solid start doesn't have anything to do with this given the api response is json.
peerreynders
peerreynders6mo ago
Use
export default function Home() {
const data = createAsync(() => getData(), { deferStream: true });
return <main>{data()}</main>;
}
export default function Home() {
const data = createAsync(() => getData(), { deferStream: true });
return <main>{data()}</main>;
}
If you want to prevent SolidStart from streaming the response before getData() has settled.
ali
aliOP6mo ago
It happens with all apis. Also, I have logged the response ( console.log(res);) and it is fine, but in the browser I get undefined
import { createAsync, cache } from "@solidjs/router";

const getData = cache(async () => {
"use server";
const response = await fetch("http://swapi.dev/api/planets/1/");
const res = await response.json();
console.log(res);
return res;
}, "users");

export const route = {
load: () => getData(),
};

export default function Home() {
const data = createAsync(() => getData());
return <main>{data()}</main>;
}
import { createAsync, cache } from "@solidjs/router";

const getData = cache(async () => {
"use server";
const response = await fetch("http://swapi.dev/api/planets/1/");
const res = await response.json();
console.log(res);
return res;
}, "users");

export const route = {
load: () => getData(),
};

export default function Home() {
const data = createAsync(() => getData());
return <main>{data()}</main>;
}
peerreynders
peerreynders6mo ago
Because you are not using { deferStream: true } the response will start streaming before the promise from the API has settled. Once it settles Seroval will try to serialize the result to be sent to the client. Perhaps Seroval is not able to serialize the type of data that your API is returning. Supported Types
GitHub
seroval/docs/compatibility.md at main · lxsmnsyc/seroval
Stringify JS values. Contribute to lxsmnsyc/seroval development by creating an account on GitHub.
ali
aliOP6mo ago
mdynnl
mdynnl6mo ago
check the console
> Unrecognized value. Skipped inserting ...
> Unrecognized value. Skipped inserting ...
peerreynders
peerreynders6mo ago
import { createAsync, cache, type RouteDefinition } from '@solidjs/router';

type Result = {
name: string;
rotation_period: string;
orbital_period: string;
diameter: string;
climate: string;
gravity: string;
terrain: string;
surface_water: string;
population: string;
residents: Array<string>;
films: Array<string>;
createed: string;
edited: string;
url: string;
};

const dataApi = async () => {
'use server';
const response = await fetch('http://swapi.dev/api/planets/1/');
const res = (await response.json()) as Result;
console.log(res);
return res;
};

const getData = cache(dataApi, 'data');

export const route = {
load() {
console.log('loading', Date.now());
getData();
},
} satisfies RouteDefinition;

export default function Home() {
const data = createAsync(() => getData(), { deferStream: true });
return <main>{JSON.stringify(data())}</main>;
}
import { createAsync, cache, type RouteDefinition } from '@solidjs/router';

type Result = {
name: string;
rotation_period: string;
orbital_period: string;
diameter: string;
climate: string;
gravity: string;
terrain: string;
surface_water: string;
population: string;
residents: Array<string>;
films: Array<string>;
createed: string;
edited: string;
url: string;
};

const dataApi = async () => {
'use server';
const response = await fetch('http://swapi.dev/api/planets/1/');
const res = (await response.json()) as Result;
console.log(res);
return res;
};

const getData = cache(dataApi, 'data');

export const route = {
load() {
console.log('loading', Date.now());
getData();
},
} satisfies RouteDefinition;

export default function Home() {
const data = createAsync(() => getData(), { deferStream: true });
return <main>{JSON.stringify(data())}</main>;
}
ali
aliOP6mo ago
Ah, I see now. Thanks for the replies!
Want results from more Discord servers?
Add your server