Function leptos::spawn_local
source · pub fn spawn_local<F>(fut: F)
Expand description
Spawns and runs a thread-local Future
in a platform-independent way.
This can be used to interface with any async
code by spawning a task
to run a Future
.
§Limitations
You should not use spawn_local
to synchronize async
code with a
signal’s value during server rendering. The server response will not
be notified to wait for the spawned task to complete, creating a race
condition between the response and your task. Instead, use
create_resource
and <Suspense/>
to coordinate
asynchronous work with the rendering process.
async fn get_user(user: String) -> Result<String, ServerFnError> {
Ok(format!("this user is {user}"))
}
// ❌ Write into a signal from `spawn_local` on the serevr
#[component]
fn UserBad() -> impl IntoView {
let signal = create_rw_signal(String::new());
// ❌ If the rest of the response is already complete,
// `signal` will no longer exist when `get_user` resolves
#[cfg(feature = "ssr")]
spawn_local(async move {
let user_res = get_user("user".into()).await.unwrap_or_default();
signal.set(user_res);
});
view! {
<p>
"This will be empty (hopefully the client will render it) -> "
{move || signal.get()}
</p>
}
}
// ✅ Use a resource and suspense
#[component]
fn UserGood() -> impl IntoView {
// new resource with no dependencies (it will only called once)
let user = create_resource(|| (), |_| async { get_user("john".into()).await });
view! {
// handles the loading
<Suspense fallback=move || view! {<p>"Loading User"</p> }>
// handles the error from the resource
<ErrorBoundary fallback=|_| {view! {<p>"Something went wrong"</p>}}>
{move || {
user.read().map(move |x| {
// the resource has a result
x.map(move |y| {
// successful call from the server fn
view! {<p>"User result filled in server and client: "{y}</p>}
})
})
}}
</ErrorBoundary>
</Suspense>
}
}