S
SolidJS•14mo ago
polyzium

Lazy named import?

I have code that depends on an async function for data, and thus I need to await it. Making a dirty hack to adapt an async function to a sync component via signals was a much simpler thing to make than what I am about to explain. I have an async component:
async function Settings(): Promise<JSX.Element> {
...
async function Settings(): Promise<JSX.Element> {
...
the data fetcher:
async function Settings_init() {
setConfig(await invoke('config'));
// vvv No async vvv
//invoke(config).then((data)=>setConfig(data as Config))
}
async function Settings_init() {
setConfig(await invoke('config'));
// vvv No async vvv
//invoke(config).then((data)=>setConfig(data as Config))
}
and the export:
export {Settings, Settings_init};
export {Settings, Settings_init};
I searched this up on google and I tried this:
const Settings = lazy(() =>
import("./tabs/SettingsTab").then((module) => ({ default: module.Settings }))
);
const Settings = lazy(() =>
import("./tabs/SettingsTab").then((module) => ({ default: module.Settings }))
);
But I get an error:
Type 'Promise<{ default: never; } | { default: () => Promise<Element>; }>' is not assignable to type 'Promise<{ default: Component<any>; }>'.
Type '{ default: never; } | { default: () => Promise<Element>; }' is not assignable to type '{ default: Component<any>; }'.
Type '{ default: () => Promise<JSX.Element>; }' is not assignable to type '{ default: Component<any>; }'.
The types returned by 'default(...)' are incompatible between these types.
Type 'Promise<Element>' is not assignable to type 'Element'.
Type 'Promise<{ default: never; } | { default: () => Promise<Element>; }>' is not assignable to type 'Promise<{ default: Component<any>; }>'.
Type '{ default: never; } | { default: () => Promise<Element>; }' is not assignable to type '{ default: Component<any>; }'.
Type '{ default: () => Promise<JSX.Element>; }' is not assignable to type '{ default: Component<any>; }'.
The types returned by 'default(...)' are incompatible between these types.
Type 'Promise<Element>' is not assignable to type 'Element'.
I don't really understand what went wrong here, but one thing for sure, whatever broke this, it broke it terribly. What is the fix for this, and if there isn't, should I go back to that dirty hack (see comment)?
9 Replies
polyzium
polyziumOP•14mo ago
On a side note, whenever I am working with async JS or TS, my brain literally melts and makes me want to just give up. Just to clarify, without lazy loading, this does not seem to work. If imported as-is, Solid doesn't seem to recognize this as an async component rather just a Promise with a component wrapped inside it.
thetarnav
thetarnav•14mo ago
A Component cannot return a promise in solid so the types of lazy don't accept the type of Settings
foolswisdom
foolswisdom•14mo ago
This 👆
polyzium
polyziumOP•14mo ago
Uhh okay then how do I depend on async data fetching BEFORE displaying the actual component other than to do it in lazy itself? And even then the whole lazy story with named imports repeats except you take the promise out of the component
foolswisdom
foolswisdom•14mo ago
In general, owners (which you don't need to worry about, but they affect:) context and reactive scope tracking and cleanups depend on synchronous execution. Anything after an await is outside of the owner system, so accepting async components would mean that the entirety of the JSX section would always be without an owner (which would not be okay unless you had absolutely nothing reactive there. Use a show component? Or wrap settings with suspense (and wrap fetching in a resource)? This doesn't really have to do with named components, your code will work (or not work) equally whether it is a default export or not Lazy is basically an async function that sets a signal when it resolves, and only shows anything once it resolves. Except that it uses resources / suspense as the mechanism
polyzium
polyziumOP•14mo ago
This could work but again I feel like this is yet another dirty hack, as you're "adapting" async to sync instead of being true async Does it have any advantages over using a store for mutation purposes?
foolswisdom
foolswisdom•14mo ago
Well, components cannot be pure async. But I agree, I also feel like using show and a signal is dirty, and prefer suspense It is completely orthogonal If you want the fetched data to be a store instead of a signal, you can use the storage option for the resource #solid-primitives has a drop in implementation for that The advantage of using a resource and store suspense is that you don't need a show component I suggest reading this page to understand suspense https://docs.solidjs.com/references/api-reference/control-flow/Suspense From the third section
polyzium
polyziumOP•14mo ago
I think I kinda understand what you were on, it's roughly the same thing as in effects since it has to "detect" the signals/stores/resources/etc used inside the function (JSX elements in this case), so I presume suspense works the same way Another question, I have a routing system that immediately mounts the components on parent mount, and as I switch between the routes, they are not re-rendered/demounted/etc, they are just stored in memory So let's say I execute an entry function once I click on a tab, and it fetches the resource again. Will Suspense display fallback in this case, or will it display whatever WAS there while the new fetch is going? Can't really tell, but it seems like it'd display fallback Guess figured out how this works now @foolswisdom Thank you for taking your time and for the answers
mdynnl
mdynnl•14mo ago
Want results from more Discord servers?
Add your server