createResource returning undefined when data is fetched

I'm just learning solid and did something like a hook? maybe? dunno. Anyways, I'm just calling createResource with a fetch on it and returning it's json. But, for any reason, that fn is returning undefined, even when the data is properly fetched("tested" by logging the json). Code:
const useFetch = <T>(p: UseFetchParams) => {
const [url] = createSignal(createUrl(p));

const [data] = createResource<T>(async () => {
return await fetch(url()).then(async (res) => (await res.json()) as T);
});

return { data, didFetch: data() !== undefined };
};
const useFetch = <T>(p: UseFetchParams) => {
const [url] = createSignal(createUrl(p));

const [data] = createResource<T>(async () => {
return await fetch(url()).then(async (res) => (await res.json()) as T);
});

return { data, didFetch: data() !== undefined };
};
75 Replies
Sun「無用」
Sun「無用」16mo ago
If I do something like console.log(data()) it would be undefined, every time I try to use it.
REEEEE
REEEEE16mo ago
Will url have an initial value when the resource is called? I see you're calling createUrl(p) but does it return a url when the useFetch is used? My guess is that the resource isn't rerun
Sun「無用」
Sun「無用」16mo ago
what?
REEEEE
REEEEE16mo ago
If you want the resource to rerun based on the url signal then you need to pass it in as a source as the first parameter of createResource
Sun「無用」
Sun「無用」16mo ago
I'm not wanting to rerun it yet Just wanting for it to work.
REEEEE
REEEEE16mo ago
Okay, try replacing url() with a static url to fetch from
Sun「無用」
Sun「無用」16mo ago
...
REEEEE
REEEEE16mo ago
I'm trying to see where the issue is
Sun「無用」
Sun「無用」16mo ago
Lightshot
Screenshot
Captured with Lightshot
REEEEE
REEEEE16mo ago
What?
Sun「無用」
Sun「無用」16mo ago
. I didn't understand anything from that
REEEEE
REEEEE16mo ago
Okay, here try this.
const useFetch = <T>(p: UseFetchParams) => {
const [url] = createSignal(createUrl(p));

const [data] = createResource<T>(async () => {
return await fetch('https://jsonplaceholder.typicode.com/posts').then(async (res) => (await res.json()) as T);
});

return { data, didFetch: data() !== undefined };
};
const useFetch = <T>(p: UseFetchParams) => {
const [url] = createSignal(createUrl(p));

const [data] = createResource<T>(async () => {
return await fetch('https://jsonplaceholder.typicode.com/posts').then(async (res) => (await res.json()) as T);
});

return { data, didFetch: data() !== undefined };
};
Does this return not undefined
Sun「無用」
Sun「無用」16mo ago
That'll return undefined since it's the same code
REEEEE
REEEEE16mo ago
You tried it?
Sun「無用」
Sun「無用」16mo ago
It's the same code, it should have the same output. If your question is if the url is valid, yes it is correct.
REEEEE
REEEEE16mo ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
REEEEE
REEEEE16mo ago
It doesn't have the same output,
Sun「無用」
Sun「無用」16mo ago
it should have, though.
REEEEE
REEEEE16mo ago
Why?
Sun「無用」
Sun「無用」16mo ago
. and the url is valid.
REEEEE
REEEEE16mo ago
The issue is the url that the resource is trying to access. Meaning, url doesn't have a valid value. If you console.log url() inside the resource before the return what do you get?
Sun「無用」
Sun「無用」16mo ago
A valid url. Like I said, the url is valid.
REEEEE
REEEEE16mo ago
the url itself that you want to fetch from might be valid. I'm saying that the url signal doesn't have a valid value yet Yes, I understand
Sun「無用」
Sun「無用」16mo ago
yes, it does. It literally fetchs. If I do this
createResource(async () => await fetch(url()).then(res => {
console.log(res)
return res.json();
}));
createResource(async () => await fetch(url()).then(res => {
console.log(res)
return res.json();
}));
This would print a valid response But the return of createResource would still be undefined
REEEEE
REEEEE16mo ago
okay, so where are you using the data value?
Sun「無用」
Sun「無用」16mo ago
In a component
REEEEE
REEEEE16mo ago
Could you show how you're using it? I can't seem to replicate it, so the issue could be something else Or make a reproduction in the playground
Sun「無用」
Sun「無用」16mo ago
const {data} = useFetch({url})}}
REEEEE
REEEEE16mo ago
Where is the data function being used?
Sun「無用」
Sun「無用」16mo ago
Im passing to other components why is that relevant?
REEEEE
REEEEE16mo ago
Because I can't replicate the issue, so it could be something else. If you think the issue is still createResource, can you make a minimal reproduction of the issue in the playground
REEEEE
REEEEE16mo ago
Okay, putting this in the playground I don't get undefined https://playground.solidjs.com/anonymous/8e08f3af-dcea-482d-a1cd-1de21d46fbec
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
REEEEE
REEEEE16mo ago
So, the issue could be something else..
Sun「無用」
Sun「無用」16mo ago
solid problem them bc it doesnt work locally
REEEEE
REEEEE16mo ago
It could be how you're using the data value Could you show how you're using it? You say you're passing it to components, but how are the components using it?
Sun「無用」
Sun「無用」16mo ago
Im just doing prop spreading. { ...data() }
REEEEE
REEEEE16mo ago
okay, what if you do {...data()}
Sun「無用」
Sun「無用」16mo ago
I just did a typo there, not used to solid
REEEEE
REEEEE16mo ago
Ah okay. Hmm and console logging the data in a createEffect like I did in the playground example still prints out undefined? in the parent component that uses the useFetch
Sun「無用」
Sun「無用」16mo ago
yes, even if I do it outside or ir inside a createEfct
REEEEE
REEEEE16mo ago
outside a createEffect it will be undefined
Sun「無用」
Sun「無用」16mo ago
the data is just always undedined
REEEEE
REEEEE16mo ago
Okay, the best way for me to help you find out the issue is if you can make a reproduction in the playground I'm not getting any info to be able to tell what the issue is
Sun「無用」
Sun「無用」16mo ago
sec, my laptop's keyboard is a bit broken
Sun「無用」
Sun「無用」16mo ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Sun「無用」
Sun「無用」16mo ago
Kinda same, at least
REEEEE
REEEEE16mo ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
REEEEE
REEEEE16mo ago
replace use of didFetch with joke()
REEEEE
REEEEE16mo ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Sun「無用」
Sun「無用」16mo ago
? that shouldn't change anything?
REEEEE
REEEEE16mo ago
didFetch isn't reactive
Sun「無用」
Sun「無用」16mo ago
what about it?
REEEEE
REEEEE16mo ago
so it will always be false
Sun「無用」
Sun「無用」16mo ago
But if I do it without the show, it's still undefined.
REEEEE
REEEEE16mo ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Sun「無用」
Sun「無用」16mo ago
Locally it goes to the fallback forever
REEEEE
REEEEE16mo ago
Which fallback? I removed Show in that example
Sun「無用」
Sun「無用」16mo ago
It just shows nothing* It's undefined. And why does a random fn changes everything?
REEEEE
REEEEE16mo ago
Because variables aren't reactive
const [signal, setSignal] = createSignal(1)

const nextValue = signal()

const nextValueFn = () => signal()
const [signal, setSignal] = createSignal(1)

const nextValue = signal()

const nextValueFn = () => signal()
Here nextValue won't update when the signal changes, but nextValueFn will
Sun「無用」
Sun「無用」16mo ago
But both are calling the signal both of them should be changed
REEEEE
REEEEE16mo ago
Yes, but in Solid only functions are tracked and updated It's the reason why using console.log outside a createEffect won't update
const [signal, setSignal] = createSignal(1)

console.log(signal())
const [signal, setSignal] = createSignal(1)

console.log(signal())
This will print 1 and then never print when the signal updates
Sun「無用」
Sun「無用」16mo ago
and wait, that doesn't work.
REEEEE
REEEEE16mo ago
If you want to use didFetch without using a function explicitly, you can do it this way https://playground.solidjs.com/anonymous/5ec53eb0-36be-4358-9af0-d7487f6adcad But you can't destructure the return of useFetch
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
Sun「無用」
Sun「無用」16mo ago
https://prnt.sc/nInWrBQEVKhl Locally.
<div class={styles.App}>
<h1>Joke:</h1>
<Show when={didFetch()} fallback={<p>Could not load the joke.</p>}>
<Joke setup={joke()!.setup} punchline={joke()!.punchline} />
</Show>
</div>
<div class={styles.App}>
<h1>Joke:</h1>
<Show when={didFetch()} fallback={<p>Could not load the joke.</p>}>
<Joke setup={joke()!.setup} punchline={joke()!.punchline} />
</Show>
</div>
Lightshot
Screenshot
Captured with Lightshot
REEEEE
REEEEE16mo ago
hmmm didFetch is a function?
return { data, didFetch: () => data() !== undefined };
return { data, didFetch: () => data() !== undefined };
Sun「無用」
Sun「無用」16mo ago
yes, I'm even calling it.
REEEEE
REEEEE16mo ago
Hmmm, and the fallback isn't showing?
Sun「無用」
Sun「無用」16mo ago
no, just a blank page which just means it's undefined.
REEEEE
REEEEE16mo ago
Any errors in the console? Because if nothing is showing up then it's something else At least Joke: should be showing
Sun「無用」
Sun「無用」16mo ago
No, just vite stuff.
REEEEE
REEEEE16mo ago
The browser console?
Sun「無用」
Sun「無用」16mo ago
Both.
REEEEE
REEEEE16mo ago
If <h1>Joke:</h1> from here is not showing up, it must be something else
<div class={styles.App}>
<h1>Joke:</h1>
<Show when={didFetch()} fallback={<p>Could not load the joke.</p>}>
<Joke setup={joke()!.setup} punchline={joke()!.punchline} />
</Show>
</div>
<div class={styles.App}>
<h1>Joke:</h1>
<Show when={didFetch()} fallback={<p>Could not load the joke.</p>}>
<Joke setup={joke()!.setup} punchline={joke()!.punchline} />
</Show>
</div>
Carlo Nyte
Carlo Nyte13mo ago
Was this ever resolved?