Browse Source

feat: useeffect implemented

Jonathan Kelley 3 năm trước cách đây
mục cha
commit
64edc6e1b1

+ 3 - 0
packages/hooks/src/lib.rs

@@ -16,6 +16,9 @@ pub use usefuture::*;
 mod usecallback;
 pub use usecallback::*;
 
+mod useeffect;
+pub use useeffect::*;
+
 #[macro_export]
 /// A helper macro for using hooks in async environements.
 ///

+ 2 - 6
packages/hooks/src/usecallback.rs

@@ -7,7 +7,6 @@ use std::future::Future;
 
 pub fn use_callback<I, G: UseFutureDep, F: Future<Output = ()> + 'static>(
     cx: &ScopeState,
-    //
     g: G,
     f: impl FnMut(I, G::Out) -> F,
 ) -> &UseCallback<I, G::Out>
@@ -26,7 +25,7 @@ where
 
 pub struct UseCallback<I, T> {
     f: Rc<RefCell<Option<Box<dyn FnMut(I, T)>>>>,
-    f2: Box<dyn Fn(I)>, // f: Rc<RefCell<Option<Box<dyn FnMut(I, T)>>>>,
+    f2: Box<dyn Fn(I)>,
 }
 
 impl<I: 'static, T> std::ops::Deref for UseCallback<I, T> {
@@ -37,10 +36,6 @@ impl<I: 'static, T> std::ops::Deref for UseCallback<I, T> {
     }
 }
 
-trait MyThing {}
-impl<A> MyThing for Box<dyn Fn(A)> {}
-impl<A, B> MyThing for Box<dyn Fn(A, B)> {}
-
 #[test]
 fn demo() {
     use dioxus_core::prelude::*;
@@ -53,6 +48,7 @@ fn demo() {
         });
 
         let onsubmit = use_callback(&cx, (name,), my_callback);
+
         async fn my_callback(event: UiEvent<()>, name: (i32,)) {
             //
         }

+ 81 - 0
packages/hooks/src/useeffect.rs

@@ -0,0 +1,81 @@
+use dioxus_core::{ScopeState, TaskId};
+use std::{any::Any, cell::Cell, future::Future};
+
+use crate::UseFutureDep;
+
+/// A hook that provides a future that executes after the hooks have been applied
+///
+/// Whenever the hooks dependencies change, the future will be re-evaluated.
+/// If a future is pending when the dependencies change, the previous future
+/// will be allowed to continue
+///
+/// - dependencies: a tuple of references to values that are PartialEq + Clone
+pub fn use_effect<'a, T: 'static, F: Future<Output = T> + 'static, D: UseFutureDep>(
+    cx: &'a ScopeState,
+    dependencies: D,
+    future: impl FnOnce(D::Out) -> F,
+) -> &'a UseEffect {
+    let state = cx.use_hook(move |_| UseEffect {
+        needs_regen: Cell::new(true),
+        task: Cell::new(None),
+        dependencies: Vec::new(),
+    });
+
+    if dependencies.clone().apply(&mut state.dependencies) || state.needs_regen.get() {
+        // We don't need regen anymore
+        state.needs_regen.set(false);
+
+        // Create the new future
+        let fut = future(dependencies.out());
+
+        state.task.set(Some(cx.push_future(async move {
+            fut.await;
+        })));
+    }
+
+    state
+}
+
+pub struct UseEffect {
+    needs_regen: Cell<bool>,
+    task: Cell<Option<TaskId>>,
+    dependencies: Vec<Box<dyn Any>>,
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[allow(unused)]
+    #[test]
+    fn test_use_future() {
+        use dioxus_core::prelude::*;
+
+        struct MyProps {
+            a: String,
+            b: i32,
+            c: i32,
+            d: i32,
+            e: i32,
+        }
+
+        fn app(cx: Scope<MyProps>) -> Element {
+            // should only ever run once
+            use_effect(&cx, (), |_| async move {
+                //
+            });
+
+            // runs when a is changed
+            use_effect(&cx, (&cx.props.a,), |(a,)| async move {
+                //
+            });
+
+            // runs when a or b is changed
+            use_effect(&cx, (&cx.props.a, &cx.props.b), |(a, b)| async move {
+                //
+            });
+
+            None
+        }
+    }
+}