docs: even more docs

This commit is contained in:
Jonathan Kelley committed 2022-03-06 20:37:57 -05:00
1 parent a4ab2d9de0
commit 0f87ebb277
25 files changed
+986 -174

No files matched your search

+1
View File
@@ -0,0 +1 @@
# Coroutines
+89 -7
View File
@@ -4,19 +4,101 @@ Not all apps you'll build can be self-contained with synchronous code. You'll of
So far, we've only talked about building apps with synchronous code, so this chapter will focus integrating asynchronous code into your app.
## The Runtime
By default, Dioxus-Desktop ships with the `Tokio` runtime and automatically sets everything up for you.
By default, Dioxus-Desktop ships with the `Tokio` runtime and automatically sets everything up for you. This is currently not configurable, though it would be easy to write an integration for Dioxus desktop that uses a different asynchronous runtime.
## Send/Sync
Writing apps that deal with Send/Sync can be frustrating at times. Under the hood, Dioxus is not currently thread-safe, so any async code you write does *not* need to be `Send/Sync`. That means Cell/Rc/RefCell are all fair game.
Writing apps that deal with Send/Sync can be frustrating at times. Under the hood, Dioxus is not currently thread-safe, so any async code you write does *not* need to be `Send/Sync`. That means that you can use non-thread-safe structures like `Cell`, `Rc`, and `RefCell`.
All async code in your app is polled on a `LocalSet`, so you can also use `tokio::spawn_local`.
## Spawning a future
Currently, all futures in Dioxus must be `'static`. To spawn a future, simply call `cx.spawn()`.
```rust
rsx!{
button {
onclick: move |_| cx.spawn(async move {
let result = fetch_thing().await;
})
}
}
```
Calling `spawn` will give you a `JoinHandle` which lets you cancel or pause the future.
## Setting state from within a future
All async code in your app is polled on a `LocalSet`, so any async code we w
If you start to write some async code, you'll quickly be greeted with the infamous error about borrowed items in static closures.
```
error[E0759]: `cx` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> examples/tasks.rs:13:27
|
12 | fn app(cx: Scope) -> Element {
| ----- this data with an anonymous lifetime `'_`...
13 | let count = use_state(&cx, || 0);
| ^^^ ...is used here...
14 |
15 | use_future(&cx, (), move |_| {
| ---------- ...and is required to live as long as `'static` here
|
note: `'static` lifetime requirement introduced by this bound
--> /Users/jonkelley/Development/dioxus/packages/hooks/src/usefuture.rs:25:29
|
25 | F: Future<Output = T> + 'static,
| ^^^^^^^
For more information about this error, try `rustc --explain E0759`.
error: could not compile `dioxus` due to previous error
```
Rustc tends to provide great feedback in its errors, but this particular error is actually quite unhelpful. For reference, here's our code:
```rust
fn app(cx: Scope) -> Element {
let count = use_state(&cx, || 0);
cx.spawn(async move {
tokio::time::sleep(Duration::from_millis(1000)).await;
count += 1;
});
cx.render(rsx! {
button {
onclick: move |_| count.set(0),
"Reset the count"
}
})
}
```
Simple, right? We spawn a future that updates the value after one second has passed. Well, yes, and no. Our `count` value is only valid for the lifetime of this component, but our future could still be running even after the component re-renders. By default, Dioxus places a requirement on all futures to be `'static`, meaning they can't just borrow state from our hooks outright.
To get around this, we need to get a `'static` handle to our state. All Dioxus hooks implement `Clone`, so you simply need to call clone before spawning your future. Any time you get the particular error above, make sure you call `Clone` or `ToOwned`.
```rust
cx.spawn({
let mut count = count.clone();
async move {
tokio::time::sleep(Duration::from_millis(1000)).await;
count += 1;
}
});
```
To make this a little bit easier, Dioxus exports the `to_owned!` macro which will create a binding as shown above, which can be quite helpful when dealing with many values.
```rust
cx.spawn({
to_owned![count, age, name, description, etc];
async move {
tokio::time::sleep(Duration::from_millis(1000)).await;
count += 1;
}
});
```
> This section is currently under construction! 🏗
+8
View File
@@ -0,0 +1,8 @@
# Updating State
After your future has been spawned, you might want to update the state of our UI. Possible implementations might include:
- A loading state
- A transition state
- Showing failures
- Listening to sockets and updating the app
+1
View File
@@ -0,0 +1 @@
# WebSockets
+1
View File
@@ -0,0 +1 @@
# UseFuture