(app: Component, props: P) -> VirtualDom {
/// In debug, this should also toss a warning.
#[test]
fn test_memory_leak() {
- fn app(cx: Scope<()>) -> Element {
+ fn app(cx: Scope) -> Element {
let val = cx.use_hook(|_| 0, |f| f);
*val += 1;
@@ -68,7 +68,7 @@ fn test_memory_leak() {
})
}
- fn child(cx: Scope<()>) -> Element {
+ fn child(cx: Scope) -> Element {
rsx!(cx, div { "goodbye world" })
}
@@ -85,7 +85,7 @@ fn test_memory_leak() {
#[test]
fn memo_works_properly() {
- fn app(cx: Scope<()>) -> Element {
+ fn app(cx: Scope) -> Element {
let val = cx.use_hook(|_| 0, |f| f);
*val += 1;
@@ -164,7 +164,7 @@ fn free_works_on_root_props() {
#[test]
fn free_works_on_borrowed() {
- fn app(cx: Scope<()>) -> Element {
+ fn app(cx: Scope) -> Element {
cx.render(rsx! {
child(a: "alpha", b: "asd".to_string())
})
@@ -203,7 +203,7 @@ fn free_works_on_root_hooks() {
}
}
- fn app(cx: Scope<()>) -> Element {
+ fn app(cx: Scope) -> Element {
let name = cx.use_hook(|_| Droppable(String::from("asd")), |f| f);
rsx!(cx, div { "{name.0}" })
}
@@ -214,7 +214,7 @@ fn free_works_on_root_hooks() {
#[test]
fn old_props_arent_stale() {
- fn app(cx: Scope<()>) -> Element {
+ fn app(cx: Scope) -> Element {
dbg!("rendering parent");
let cnt = cx.use_hook(|_| 0, |f| f);
*cnt += 1;
@@ -261,7 +261,7 @@ fn old_props_arent_stale() {
#[test]
fn basic() {
- fn app(cx: Scope<()>) -> Element {
+ fn app(cx: Scope) -> Element {
rsx!(cx, div {
child(a: "abcdef".to_string())
})
diff --git a/packages/core/tests/vdom_rebuild.rs b/packages/core/tests/vdom_rebuild.rs
index 21619d9c2..5d1dbcdf8 100644
--- a/packages/core/tests/vdom_rebuild.rs
+++ b/packages/core/tests/vdom_rebuild.rs
@@ -44,7 +44,7 @@ fn lists_work() {
static App: Component = |cx| {
cx.render(rsx!(
h1 {"hello"}
- {(0..6).map(|f| rsx!(span{ "{f}" }))}
+ (0..6).map(|f| rsx!(span{ "{f}" }))
))
};
let mut vdom = VirtualDom::new(App);
diff --git a/packages/desktop/Cargo.toml b/packages/desktop/Cargo.toml
index a132bc513..d088aa04c 100644
--- a/packages/desktop/Cargo.toml
+++ b/packages/desktop/Cargo.toml
@@ -37,4 +37,3 @@ tokio_runtime = ["tokio"]
[dev-dependencies]
dioxus-hooks = { path = "../hooks" }
-simple_logger = "1.13.0"
diff --git a/packages/desktop/examples/async.rs b/packages/desktop/examples/async.rs
index 2c6901f85..056e7b591 100644
--- a/packages/desktop/examples/async.rs
+++ b/packages/desktop/examples/async.rs
@@ -9,22 +9,18 @@ fn main() {
dioxus_desktop::launch(app);
}
-fn app(cx: Scope<()>) -> Element {
+fn app(cx: Scope) -> Element {
let count = use_state(&cx, || 0);
- // push the futureo on initialization
- cx.use_hook(
- |_| {
- cx.push_future({
- let count = count.for_async();
- async move {
- tokio::time::sleep(Duration::from_millis(1000)).await;
- *count.get_mut() += 1;
- }
- });
- },
- |_| {},
- );
+ use_future(&cx, || {
+ let count = count.for_async();
+ async move {
+ loop {
+ tokio::time::sleep(Duration::from_millis(1000)).await;
+ *count.modify() += 1;
+ }
+ }
+ });
cx.render(rsx! {
div {
diff --git a/packages/hooks/README.md b/packages/hooks/README.md
index 11e008c44..18133e40b 100644
--- a/packages/hooks/README.md
+++ b/packages/hooks/README.md
@@ -4,58 +4,19 @@ This crate includes some basic useful hooks for dioxus:
- use_state
- use_ref
-- use_collection
-- use_task
-- use_signal
+- use_future
+- use_coroutine
## use_state
-The king daddy of state hooks.
+The primary mechanism of stored state.
You can always use it "normally" with the `split` method:
```rust
-// Normal usage:
+// Rusty-smart-pointer usage:
let value = use_state(&cx, || 10);
// "Classic" usage:
let (value, set_value) = use_state(&cx, || 0).split();
```
-
-## use_ref
-
-
-## use_rwlock
-A multithreaded form of RwLock for use in tasks
-```rust
-let val = use_rwlock(cx, || 10);
-use_task((), || async loop {
- *val.write().unwrap() += 1;
- async_std::task::delay(Duration::from_ms(1000)).await;
-});
-use_task((), || async loop {
- *val.write().unwrap() -= 1;
- async_std::task::delay(Duration::from_ms(500)).await;
-});
-```
-
-## use_hashmap
-Store a memoized collection with similar semantics to use_state. Comes with a bunch of utility methods to make working with collections easier. Is essentially a wrapper over the immutable hashmap in im-rc.
-
-```rust
-let todos = use_hashmap(cx, |map| map.insert("bob", "bill"));
-cx.render(rsx!(
- button { onclick: move |_| todos.insert("bob", "bill")
- "add random todo"
- }
-)
-
-```
-
-## use_task
-
-use_task submits a task to the dioxus task queue to be progressed during Dioxus's async event loop. The task must not return anything
-
-
-## use_signal
-
diff --git a/packages/hooks/src/lib.rs b/packages/hooks/src/lib.rs
index 1a38ed172..0050d1779 100644
--- a/packages/hooks/src/lib.rs
+++ b/packages/hooks/src/lib.rs
@@ -1,5 +1,5 @@
mod usestate;
-pub use usestate::{use_state, AsyncUseState, UseState};
+pub use usestate::{use_state, UseState};
mod useref;
pub use useref::*;
@@ -16,5 +16,45 @@ pub use usefuture::*;
mod usesuspense;
pub use usesuspense::*;
-// mod usemodel;
-// pub use usemodel::*;
+#[macro_export]
+macro_rules! to_owned {
+ ($($es:ident),+) => {$(
+ #[allow(unused_mut)]
+ let mut $es = $es.to_owned();
+ )*}
+}
+
+/// Calls `for_async` on the series of paramters.
+///
+/// If the type is Clone, then it will be cloned. However, if the type is not `clone`
+/// then it must have a `for_async` method for Rust to lower down into.
+///
+/// See: how use_state implements `for_async` but *not* through the trait.
+#[macro_export]
+macro_rules! for_async {
+ ($($es:ident),+) => {$(
+ #[allow(unused_mut)]
+ let mut $es = $es.for_async();
+ )*}
+}
+
+/// This is a marker trait that uses decoherence.
+///
+/// It is *not* meant for hooks to actually implement, but rather defer to their
+/// underlying implementation if they *don't* implement the trait.
+///
+///
+pub trait AsyncHook {
+ type Output;
+ fn for_async(self) -> Self::Output;
+}
+
+impl AsyncHook for T
+where
+ T: ToOwned,
+{
+ type Output = T;
+ fn for_async(self) -> Self::Output {
+ self
+ }
+}
diff --git a/packages/hooks/src/usestate.rs b/packages/hooks/src/usestate.rs
index 88caea82d..9a02d6bcb 100644
--- a/packages/hooks/src/usestate.rs
+++ b/packages/hooks/src/usestate.rs
@@ -2,20 +2,9 @@ use dioxus_core::prelude::*;
use std::{
cell::{Cell, Ref, RefCell, RefMut},
fmt::{Debug, Display},
- ops::Not,
rc::Rc,
};
-pub trait UseStateA<'a, T> {
- fn use_state(&self, initial_state_fn: impl FnOnce() -> T) -> UseState<'a, T>;
-}
-
-impl<'a, P, T> UseStateA<'a, T> for Scope<'a, P> {
- fn use_state(&self, initial_state_fn: impl FnOnce() -> T) -> UseState<'a, T> {
- use_state(self.scope, initial_state_fn)
- }
-}
-
/// Store state between component renders!
///
/// ## Dioxus equivalent of useState, designed for Rust
@@ -109,6 +98,7 @@ where
UseState { inner: self.inner }
}
}
+
impl Debug for UseState<'_, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.inner.current_val)
@@ -157,21 +147,21 @@ impl<'a, T: 'static> UseState<'a, T> {
})
}
- pub fn for_async(&self) -> AsyncUseState {
- AsyncUseState {
- re_render: self.inner.update_callback.clone(),
- wip: self.inner.wip.clone(),
- inner: self.inner.current_val.clone(),
- }
+ pub fn for_async(self) -> UseState<'static, T> {
+ todo!()
}
- pub fn split_for_async(&'a self) -> (&'a Self, AsyncUseState) {
- (self, self.for_async())
+ pub fn wtih(self, f: impl FnOnce(&mut T)) {
+ let mut val = self.inner.wip.borrow_mut();
+
+ if let Some(inner) = val.as_mut() {
+ f(inner);
+ }
}
}
impl<'a, T: 'static + ToOwned> UseState<'a, T> {
- /// Gain mutable access to the new value via RefMut.
+ /// Gain mutable access to the new value via [`RefMut`].
///
/// If `modify` is called, then the component will re-render.
///
@@ -207,6 +197,35 @@ impl<'a, T> std::ops::Deref for UseState<'a, T> {
}
}
+// enable displaty for the handle
+impl<'a, T: 'static + Display> std::fmt::Display for UseState<'a, T> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", self.inner.current_val)
+ }
+}
+impl<'a, V, T: PartialEq> PartialEq for UseState<'a, T> {
+ fn eq(&self, other: &V) -> bool {
+ self.get() == other
+ }
+}
+impl<'a, O, T: std::ops::Not