S
SolidJS•5w ago
heartworm

data is rendering correctly on file save but not on page refresh

I am unsure exactly what is happening but when I refresh the page using create resource no data loads. However if I save the file in my editor suddenly the data pops up. I am assuming this is an issue with SSR somehow, but I do not understand what I am doing wrong.
import { createEffect, createResource, Show } from "solid-js";
import { createExternalApi } from "~/server/externalApi";

const resource = async () => {
const externalApi = await createExternalApi();
const userInfo = await externalApi.getUserInfo();
const userInfoResponse = await userInfo.response?.json();

return userInfoResponse;
}

export const UserDetails = () => {
const [data] = createResource(resource);

return (
<>
<Show when={data.loading}>Loading</Show>
<Show when={data.error}>Error</Show>
<Show when={data()}>{(data) => data().username}</Show> // only renders on file save
</>
);
}
import { createEffect, createResource, Show } from "solid-js";
import { createExternalApi } from "~/server/externalApi";

const resource = async () => {
const externalApi = await createExternalApi();
const userInfo = await externalApi.getUserInfo();
const userInfoResponse = await userInfo.response?.json();

return userInfoResponse;
}

export const UserDetails = () => {
const [data] = createResource(resource);

return (
<>
<Show when={data.loading}>Loading</Show>
<Show when={data.error}>Error</Show>
<Show when={data()}>{(data) => data().username}</Show> // only renders on file save
</>
);
}
Any thoughts here would be greatly appreciated. I have been banging my head against the wall on this one.
110 Replies
REEEEE
REEEEE•5w ago
Wrap the data().username in a fragment or any html element
heartworm
heartwormOP•4w ago
Unfortunately even doing something like <div>{data().username}</div> is not working Anyone else have any ideas?
Madaxen86
Madaxen86•4w ago
Can you share the "server/externalAPI" file?
heartworm
heartwormOP•4w ago
@Madaxen86 It's just returning an API. What I've found debugging through this is that when the component loads the first time it's not even calling the async function. When I save the file it does run the async function and everything works correctly. Is it possibly an issue with it being in the server directory and running on the server?\
REEEEE
REEEEE•4w ago
How are you rendering the component?
heartworm
heartwormOP•4w ago
Yeah, so data is just undefined when I refresh the page When I save, suddenly it's available The code above is what I have
REEEEE
REEEEE•4w ago
That's all the code?
heartworm
heartwormOP•4w ago
Yes
REEEEE
REEEEE•4w ago
How does UserDetails get rendered
heartworm
heartwormOP•4w ago
What's weird is when I use a regular fetch in there it works perfect So it might be the way this external API is working I am just perplexed why the API wouldn't work on a refresh but then on a save
REEEEE
REEEEE•4w ago
I think the component isn't getting rendered properly so the hmr "fixes" it when you save
heartworm
heartwormOP•4w ago
What would cause it not to be rendered properly?
REEEEE
REEEEE•4w ago
Props destructuring possibly some invisible error
heartworm
heartwormOP•4w ago
Yeah the weird thing is there is no error
REEEEE
REEEEE•4w ago
Are you able to reproduce the issue either in the playground or in a fresh project?
heartworm
heartwormOP•4w ago
I don't think so, I think this is specific to me Because it works otherwise with fetch
REEEEE
REEEEE•4w ago
Hm, does createExternalApi use use server ?
heartworm
heartwormOP•4w ago
No I did try it and it didn't make a difference So, data is undefined and never gets reevaluated on page refresh On save it does
REEEEE
REEEEE•4w ago
What if you wrap the resource with another function like
const [data] = createResource(async () => await resource());
const [data] = createResource(async () => await resource());
heartworm
heartwormOP•4w ago
And I see it in the console, it logs data multiple times Let me see Crashed the development server lol
REEEEE
REEEEE•4w ago
Progress lol Wonder why
heartworm
heartwormOP•4w ago
I dunno
REEEEE
REEEEE•4w ago
Any errors?
heartworm
heartwormOP•4w ago
Like I said when I log data() on page refresh... it doesn't reevaluate or anything. When I save, it reevaluates a couple of times until it finally gets something other than undefined. data is initially undefined until the server is done fetching. No errors
REEEEE
REEEEE•4w ago
Yeah I get that, but you said the dev server crashed so I was wondering if there were any errors
heartworm
heartwormOP•4w ago
I had to change it to (() => resource()); because async and await did nothing in that context Oh wait I missed something Okay so actually tried what you suggested and same result -- I forgot to call the method Refresh no data, save has data
REEEEE
REEEEE•4w ago
Did you try logging in an effect yet?
heartworm
heartwormOP•4w ago
No, let me try Yeah same thing. On a save it evaluates twice. On a refresh only once. So I get undefined on a refresh... then I get undefined and then data on a save. In the console So weird Maybe the JSON is malformed?
REEEEE
REEEEE•4w ago
🤷‍♂️ Is the resource function called? Like if you put a log in it, is it called?
heartworm
heartwormOP•4w ago
No on a page refresh. If I look in the network tab it's not making an API call. When I save it does. I am assuming there is some error happening that's halting it And I can't see it
REEEEE
REEEEE•4w ago
Yeah so try putting some logs in the function and output each value for externalApi, userInfo, and userInfoResponse and see what you get
heartworm
heartwormOP•4w ago
On refresh nothing logs -- on file save it all logs lol wth It's not even running the function on a refresh
REEEEE
REEEEE•4w ago
so maybe the component isn't being rendered
heartworm
heartwormOP•4w ago
It's not for some reason Is this a router thing?
REEEEE
REEEEE•4w ago
idk what does the rest of the app look like? the part that renders the UserDetails component
heartworm
heartwormOP•4w ago
That is the entire UserDetails component
REEEEE
REEEEE•4w ago
.... Where do you use it Where do you do <UserDetails />
heartworm
heartwormOP•4w ago
import { A } from "@solidjs/router"; import { ParentComponent } from "solid-js"; import { UserDetails } from "./UserDetails"; import { WinnerTicker } from "./WinnerTicker"; const AppLayout: ParentComponent = (props) => { return ( <> <header class="@container flex items-center justify-between pt-2 pr-5 pb-2 pl-5"> <UserDetails /> </header> <WinnerTicker /> {props.children} </> ); } export default AppLayout; It's being used in a layout component that wraps the children
REEEEE
REEEEE•4w ago
And how is AppLayout used?
heartworm
heartwormOP•4w ago
import { Router } from "@solidjs/router"; import { FileRoutes } from "@solidjs/start/router"; import { Suspense } from "solid-js"; import { initFlowbite } from 'flowbite'; import { onMount } from 'solid-js'; import "./app.css"; export default function App() { onMount(() => { initFlowbite(); }) return ( <Router root={props => ( <> <Suspense>{props.children}</Suspense> </> )} > <FileRoutes /> </Router> ); }
REEEEE
REEEEE•4w ago
Where is <AppLayout>?
heartworm
heartwormOP•4w ago
Well AppLayout is just a layout so it doesn't need to be placed directly because the directory structure is app/(layout)/
REEEEE
REEEEE•4w ago
Or is it a route right
heartworm
heartwormOP•4w ago
Within the app directory is the UserDetails And there is a (layout).tsx file
REEEEE
REEEEE•4w ago
hm okay, if you put other html in the UserDetails component, do you see it?
heartworm
heartwormOP•4w ago
Which is AppLayout Yes
REEEEE
REEEEE•4w ago
So the component is being rendered
heartworm
heartwormOP•4w ago
It is
REEEEE
REEEEE•4w ago
I have no clue
heartworm
heartwormOP•4w ago
same lol
REEEEE
REEEEE•4w ago
I saw you were using alias imports via ~
heartworm
heartwormOP•4w ago
The only thing I can think is this has something to do with the external api file
REEEEE
REEEEE•4w ago
maybe try relative?
heartworm
heartwormOP•4w ago
I moved the API creation logic inside the component and still getting the same issue
REEEEE
REEEEE•4w ago
It might not be resolving the import correctly and that's what's bugging it out Huh welp
heartworm
heartwormOP•4w ago
Yeah const userInfoResponse = await userInfo.response?.json(); I don't think the optional means anything here Or does anything
REEEEE
REEEEE•4w ago
What about removing some of the other stuff and just keep createExternalApi part
heartworm
heartwormOP•4w ago
Which stuff?
REEEEE
REEEEE•4w ago
const resource = async () => {
const externalApi = await createExternalApi();

return externalApi;
}
const resource = async () => {
const externalApi = await createExternalApi();

return externalApi;
}
heartworm
heartwormOP•4w ago
I can try that
REEEEE
REEEEE•4w ago
Or
const resource = async () => {
const externalApi = await createExternalApi();
console.log(externalApi)
return {};
}
const resource = async () => {
const externalApi = await createExternalApi();
console.log(externalApi)
return {};
}
heartworm
heartwormOP•4w ago
const resource = async () => { const URL = 'http://localhost:5000/' let extAPI = await ConnectToAPI(URL); console.log(extAPI); return JSON.stringify({}); } export const UserDetails = () => { const [data] = createResource(resource); return ( <> <Show when={data.loading}>Loading</Show> <Show when={data.error}>Error</Show> <Show when={data()}>{data()}</Show> </> ); } Works fine I get the {} where I think it should be
REEEEE
REEEEE•4w ago
do you see the console log? Try adding the userInfo part back
heartworm
heartwormOP•4w ago
No, actually
REEEEE
REEEEE•4w ago
what
heartworm
heartwormOP•4w ago
Oh wait It's logging it on the server Not the browser
REEEEE
REEEEE•4w ago
yeah it runs on the server first ssr
heartworm
heartwormOP•4w ago
Yes
REEEEE
REEEEE•4w ago
okay try adding userInfo back
heartworm
heartwormOP•4w ago
So yeah I am seeing it on the server
REEEEE
REEEEE•4w ago
but not the .json call one Just const userInfo = await externalApi.getUserInfo();
heartworm
heartwormOP•4w ago
Yes that works, I see the {} API logs
REEEEE
REEEEE•4w ago
try logging userInfo
heartworm
heartwormOP•4w ago
I am getting what I expect User { _restClient: undefined, _links: Map(0) {}, _lists: Map(0) {}, originalValues: Map(0) {}, response: undefined, username: '', email: '', lastName: '', firstName: '', dateOfBirth: 2025-04-10T23:05:52.864Z, accountBalance: 0 }
REEEEE
REEEEE•4w ago
Try doing the last part also it says response is undefined so so resource would always return undefined, idk why it works on save though
heartworm
heartwormOP•4w ago
This honestly could be a bug in that external api I will have to contact the author of it Because you're right, response is undefined When I save though it logs in the browser just fine When I refresh I get undefined on the server I guess I thought when it logged undefined it was still fetching the data But it only ever logs once On save it logs multiple times Why would it fetch once on refresh but multiple times on save?
REEEEE
REEEEE•4w ago
Not sure could just be an hmr thing
heartworm
heartwormOP•4w ago
what is hmr?
REEEEE
REEEEE•4w ago
hot module reload, the thing that lets you see your changes when you save
heartworm
heartwormOP•4w ago
I am assuming rendering but I dunno what it stands for Oh Right hmm hmr
REEEEE
REEEEE•4w ago
Does the createExternalApi stuff required something to be initialized beforehand?
heartworm
heartwormOP•4w ago
Yes
REEEEE
REEEEE•4w ago
maybe it's not ready when that component is rendered
heartworm
heartwormOP•4w ago
You have to connect to it and get an API instance back That might be true Where would I put it to make sure it's totally ready?
REEEEE
REEEEE•4w ago
Where do you create a api instance?
heartworm
heartwormOP•4w ago
In a file in a server directory It's just an async function that creates it and sends an instance back I will find the code
REEEEE
REEEEE•4w ago
hm
heartworm
heartwormOP•4w ago
import { ConnectToApi, Api } from "api-client"; let api: Api; const URL = 'http://localhost:5000/' export const createApi = async (): Promise<Api> => { const api = await ConnectToApi(URL); return api; } export const getApi = async (): Promise<Api> => { if (!api) { api = await createApi(); } return Api; } export const setApi = async (api: Api) => { api = api; } Pretty basic But I moved that ConnectToApi thing in the component and still the same result I guess I could prevent the whole app from rendering until there is an instance ready? I just don't think I should have to do that
REEEEE
REEEEE•4w ago
Do you even need this line? const userInfoResponse = await userInfo.response?.json();
heartworm
heartwormOP•4w ago
Well I have to return json, right? What else would I return?
REEEEE
REEEEE•4w ago
Return the userInfo object maybe It looks like it has the properties you'd want
heartworm
heartwormOP•4w ago
Server crashed and I get Error The value [object Object] of type "object" cannot be parsed/serialized.
REEEEE
REEEEE•4w ago
I see
heartworm
heartwormOP•4w ago
It's because it has methods on it
REEEEE
REEEEE•4w ago
You could just pull the data you want out of the object and return that Idk why the response part is undefined though
heartworm
heartwormOP•4w ago
Yeah this has to be an issue with the library because trying to pull an property out of the object and returning it does gives me the same issue
REEEEE
REEEEE•4w ago
What no way
heartworm
heartwormOP•4w ago
Yeah It's there when I save, not when I refresh I do get this game-selection:1 Unchecked runtime.lastError: The message port closed before a response was received. But not sure what it means Oh it's just chrome extensions, doesn't mean anything
REEEEE
REEEEE•4w ago
what if you log the response
heartworm
heartwormOP•4w ago
I did try another endpoint from that library that doesn't have to be authed to make a call and I had no issues I am really thinking it's this endpoint Or the way it's implemented
REEEEE
REEEEE•4w ago
maybe an auth issue?
heartworm
heartwormOP•4w ago
Possibly I will get with the library author and then get back to you I really don't think it's solid now that I've done a lot of testing Thanks for all of your help! After more playing with it I think this is an HMR issue On page refresh it's not mounting the component at all On save it does I am convinced this actually isn't the API library issue This is some sort of issue with rendering Oh wait I think I figured it out. On a page refresh the code is running in the browser and it's sending along the cookie it needs to authenticate. When it's being refreshed it's running on the server and the cookie is not there for it to be sent along and the call is failing. That's exactly what's happening. Because other non authed routes work.
import { createEffect, createResource, Show } from "solid-js";
import { ConnectToApi, User } from "api-client";

export default function UserDetails() {
const [userInfo] = createResource(async () => {
const api = await ConnectToApi('http://localhost:5000');
const userInfo = await api.getUserInfo();

return (await userInfo.response?.json()) as User;
});
debugger;

createEffect(() => {
console.log(userInfo);
console.log('entering user details');
});

return (
<>
<Show when={userInfo.loading}>Loading</Show>
<Show when={userInfo.error}>Error</Show>
<Show when={userInfo()}>{userInfo()?.username}</Show>
</>
);
}
import { createEffect, createResource, Show } from "solid-js";
import { ConnectToApi, User } from "api-client";

export default function UserDetails() {
const [userInfo] = createResource(async () => {
const api = await ConnectToApi('http://localhost:5000');
const userInfo = await api.getUserInfo();

return (await userInfo.response?.json()) as User;
});
debugger;

createEffect(() => {
console.log(userInfo);
console.log('entering user details');
});

return (
<>
<Show when={userInfo.loading}>Loading</Show>
<Show when={userInfo.error}>Error</Show>
<Show when={userInfo()}>{userInfo()?.username}</Show>
</>
);
}
This works when saving and I see it in the console in the browser When refreshing it does not
Madaxen86
Madaxen86•4w ago
You’ll need to proxy the cookies on the server. Incomplete mock:
function $authFetch(url: string, init?: RequestInit) {
if (!isServer) fetch(url, { ...init, credentials: "include" }); //include cookies on request
const cookie = getRequestEvent()?.request.headers.get("cookie") || ""; //get cookies from request and pass it them to the fetch call.
return fetch(`${import.meta.env.VITE_AUTH_HOST}${url}`, {
...init,
credentials: "include",
headers: {
...init?.headers,
cookie: cookie,
},
});
}
function $authFetch(url: string, init?: RequestInit) {
if (!isServer) fetch(url, { ...init, credentials: "include" }); //include cookies on request
const cookie = getRequestEvent()?.request.headers.get("cookie") || ""; //get cookies from request and pass it them to the fetch call.
return fetch(`${import.meta.env.VITE_AUTH_HOST}${url}`, {
...init,
credentials: "include",
headers: {
...init?.headers,
cookie: cookie,
},
});
}
heartworm
heartwormOP•4w ago
Why do I have to do this at all? Why can't I just make these calls on the client?
Madaxen86
Madaxen86•4w ago
Then you‘ll have to disable SSR. In the app.config.ts If you want to render on the server you have to be able to fetch in the server. With SSR the initial render is on the server once hydrated the app renders purely client side
heartworm
heartwormOP•4w ago
I created a discussion here on this: https://github.com/solidjs/solid/discussions/2467
GitHub
createResource and SSR ¡ solidjs solid ¡ Discussion #2467
I just started using SolidJS and I am very new. I am having a bit of trouble with createResource. Here is some example code: import { createEffect, createResource, Show } from "solid-js";...
heartworm
heartwormOP•4w ago
@Madaxen86 Is it common for folks to disable SSR in solid?
Madaxen86
Madaxen86•4w ago
If you don’t need SSR, then yes. If you want to create a page that’s SEO optimised, then absolutely not. In short: it depends
heartworm
heartwormOP•4w ago
I guess I should shouldn't use solidstart then and just stick to solid core?
Madaxen86
Madaxen86•4w ago
In app.config.ts you can set SSR:false and you have a classic SPA

Did you find this page helpful?