freya/_docs/_async.rs
1//! # Async
2//!
3//! Freya runs futures on its own executor so async tasks can update reactive
4//! state directly. The async primitives below are the building blocks: use them
5//! for one-off tasks like timers, cancelable background work, or fire-and-forget
6//! requests.
7//!
8//! ## `spawn`
9//!
10//! [`spawn`](crate::prelude::spawn) starts a future tied to the **current
11//! component scope**. When the component unmounts, the task is automatically
12//! cancelled.
13//!
14//! ```rust,no_run
15//! # use freya::prelude::*;
16//! #[derive(PartialEq)]
17//! struct DelayedCounter;
18//!
19//! impl Component for DelayedCounter {
20//! fn render(&self) -> impl IntoElement {
21//! let mut count = use_state(|| 0);
22//!
23//! Button::new()
24//! .on_press(move |_| {
25//! spawn(async move {
26//! // Some async work...
27//! *count.write() += 1;
28//! });
29//! })
30//! .child(format!("Count: {}", count.read()))
31//! }
32//! }
33//! ```
34//!
35//! `spawn` returns a [`TaskHandle`](crate::prelude::TaskHandle) that you can
36//! use to cancel the task manually. Calling [`.owned()`](crate::prelude::TaskHandle::owned)
37//! upgrades it to an [`OwnedTaskHandle`](crate::prelude::OwnedTaskHandle) that
38//! cancels the task when the last clone is dropped.
39//!
40//! ## `spawn_forever`
41//!
42//! [`spawn_forever`](crate::prelude::spawn_forever) is like `spawn` but the task
43//! is attached to the **root scope**. It keeps running until the app exits or
44//! you cancel it explicitly, regardless of the component that started it.
45//!
46//! Use it for app-wide background work (a sync loop, periodic refreshes, etc.)
47//! that should outlive the component that spawned it.
48//!
49//! ```rust,no_run
50//! # use freya::prelude::*;
51//! # fn app() -> impl IntoElement {
52//! use_hook(|| {
53//! spawn_forever(async {
54//! loop {
55//! // App-level background loop
56//! }
57//! });
58//! });
59//! # rect()
60//! # }
61//! ```
62//!
63//! ## `use_future`
64//!
65//! [`use_future`](crate::prelude::use_future) is a hook around `spawn` that
66//! exposes the future's progress as reactive state. It is convenient when you
67//! want to render different UI for *pending*, *loading*, and *fulfilled*
68//! states without managing the task by hand.
69//!
70//! ```rust,no_run
71//! # use freya::prelude::*;
72//! #[derive(PartialEq)]
73//! struct Greeting;
74//!
75//! impl Component for Greeting {
76//! fn render(&self) -> impl IntoElement {
77//! let future = use_future(|| async {
78//! // Some async work...
79//! "Hello!".to_string()
80//! });
81//!
82//! match &*future.state() {
83//! FutureState::Pending | FutureState::Loading => "Loading...".to_string(),
84//! FutureState::Fulfilled(text) => text.clone(),
85//! }
86//! }
87//! }
88//! ```
89//!
90//! The returned [`FutureTask`](crate::prelude::FutureTask) exposes
91//! [`start`](crate::prelude::FutureTask::start) and
92//! [`cancel`](crate::prelude::FutureTask::cancel) so you can restart or stop
93//! the future later.