Closed luxalpa closed 5 months ago
Not sure what the goal is during the example -- I see the panic and it is during initial route generation on the server. This kind of error would be suppressed during route generation using something like a resource. Is the idea here to run some async task, independent of the rendering process, but while rendering? There's no way to wait for the task you spawned to finish before rendering HTML.
Or of course you can just not unwrap in the places you're unwrapping; this version works fine:
#[server]
pub async fn get_user_data() -> Result<UserData, ServerFnError> {
use actix_web::HttpRequest;
use leptos_actix::extract;
let req: HttpRequest = extract().await?;
println!("Method: {:?}", req.method());
return Ok(UserData {
name: "Luxalpa".to_string(),
});
}
#[component]
pub fn FrontPage() -> impl IntoView {
spawn_local(async move {
if let Ok(site_data) = get_user_data().await {
println!("Site Data: {:?}", site_data);
}
});
view! { <div> "Front Page" </div> }
}
The code above is just a minimalistic example. My application is actually using a resource that is set as pending like this:
let resource = create_blocking_resource(
move || {},
// TODO: Figure out if this future needs to be manually cleaned up somehow
move |_| future::pending::<CardWithPrinting>(),
);
and then later (in the same function) it is fetching the data:
spawn_local(async move {
let result = get_card_printings(ids).await.unwrap().0;
self.add_to_cache(result);
});
and in add_to_cache
it is setting the resource:
// Notify resources
if let Some(resources) = in_use.remove(&card.printing.id) {
resources.iter().for_each(|r| {
r.try_set(card.clone());
});
}
Because the application needs to cache the data that comes from these resources while also providing SSR for them too. This architecture was inspired by leptos_query, but apparently it does not work well with server functions.
To be clear the panic is unrelated to server functions, it specifically has to do with unwrapping the attempt to extract an HttpRequest
during the server's initial route generation, which runs the application once to figure out all the routes you've defined. It suppresses resource loads during this, but the spawn_local
still runs, and panics when unwrapping the HttpRequest
extractor. (There is no HTTP request during that route generation process.)
In the actual example you provide, I assume that just not unwrapping here will fix your issue:
spawn_local(async move {
let result = get_card_printings(ids).await.unwrap().0;
self.add_to_cache(result);
});
// instead
spawn_local(async move {
// I'm missing the .0 here but hopefully you see what I mean
if let Ok(result) = get_card_printings(ids).await {
self.add_to_cache(result);
}
});
and likewise removing the .unwrap()
in get_card_printings
and using ?
instead if the extractor fails.
ok, thanks a lot, that actually explains some things and allowed me to workaround this.
Describe the bug When using
spawn_local
to get data from the server instead of fetching from inside a resource, then theextract
function inside the server function will cause an error:"HttpRequest should have been provided via context"
.Leptos Dependencies
To Reproduce
Additional Context Using reqwest instead of a server function seems to be a workaround.