add a way to add manual dependency tuple to memos and effects
This commit is contained in:
1 parent
2bbc609082
commit
0951a389f7
7 files changed
+106
-105
No files matched your search
@@ -0,0 +1,67 @@
|
||||
/// A dependency is a trait that can be used to determine if a effect or selector should be re-run.
|
||||
pub trait Dependency: Sized + Clone {
|
||||
/// The output of the dependency
|
||||
type Out: Clone + PartialEq + 'static;
|
||||
/// Returns the output of the dependency.
|
||||
fn out(&self) -> Self::Out;
|
||||
/// Returns true if the dependency has changed.
|
||||
fn changed(&self, other: &Self::Out) -> bool {
|
||||
self.out() != *other
|
||||
}
|
||||
}
|
||||
|
||||
impl Dependency for () {
|
||||
type Out = ();
|
||||
fn out(&self) -> Self::Out {}
|
||||
}
|
||||
|
||||
/// A dependency is a trait that can be used to determine if a effect or selector should be re-run.
|
||||
pub trait DependencyElement: 'static + PartialEq + Clone {}
|
||||
impl<T> DependencyElement for T where T: 'static + PartialEq + Clone {}
|
||||
|
||||
impl<A: DependencyElement> Dependency for &A {
|
||||
type Out = A;
|
||||
fn out(&self) -> Self::Out {
|
||||
(*self).clone()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_dep {
|
||||
(
|
||||
$($el:ident=$name:ident $other:ident,)*
|
||||
) => {
|
||||
impl< $($el),* > Dependency for ($(&$el,)*)
|
||||
where
|
||||
$(
|
||||
$el: DependencyElement
|
||||
),*
|
||||
{
|
||||
type Out = ($($el,)*);
|
||||
|
||||
fn out(&self) -> Self::Out {
|
||||
let ($($name,)*) = self;
|
||||
($((*$name).clone(),)*)
|
||||
}
|
||||
|
||||
fn changed(&self, other: &Self::Out) -> bool {
|
||||
let ($($name,)*) = self;
|
||||
let ($($other,)*) = other;
|
||||
$(
|
||||
if *$name != $other {
|
||||
return true;
|
||||
}
|
||||
)*
|
||||
false
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_dep!(A = a1 a2,);
|
||||
impl_dep!(A = a1 a2, B = b1 b2,);
|
||||
impl_dep!(A = a1 a2, B = b1 b2, C = c1 c2,);
|
||||
impl_dep!(A = a1 a2, B = b1 b2, C = c1 c2, D = d1 d2,);
|
||||
impl_dep!(A = a1 a2, B = b1 b2, C = c1 c2, D = d1 d2, E = e1 e2,);
|
||||
impl_dep!(A = a1 a2, B = b1 b2, C = c1 c2, D = d1 d2, E = e1 e2, F = f1 f2,);
|
||||
impl_dep!(A = a1 a2, B = b1 b2, C = c1 c2, D = d1 d2, E = e1 e2, F = f1 f2, G = g1 g2,);
|
||||
impl_dep!(A = a1 a2, B = b1 b2, C = c1 c2, D = d1 d2, E = e1 e2, F = f1 f2, G = g1 g2, H = h1 h2,);
|
||||
@@ -19,6 +19,9 @@ pub use map::*;
|
||||
// mod comparer;
|
||||
// pub use comparer::*;
|
||||
|
||||
mod dependency;
|
||||
pub use dependency::*;
|
||||
|
||||
mod memo;
|
||||
pub use memo::*;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::write::Writable;
|
||||
use crate::{read::Readable, ReactiveContext, ReadableRef, Signal};
|
||||
use crate::{CopyValue, ReadOnlySignal};
|
||||
use crate::{CopyValue, Dependency, ReadOnlySignal};
|
||||
use std::rc::Rc;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
@@ -153,6 +153,40 @@ impl<T: 'static> Memo<T> {
|
||||
pub fn id(&self) -> generational_box::GenerationalBoxId {
|
||||
self.inner.id()
|
||||
}
|
||||
|
||||
/// Adds an explicit dependency to the memo. If the dependency changes, the memo will rerun.
|
||||
///
|
||||
/// Signals will automatically be added as dependencies, so you don't need to call this method for them.
|
||||
///
|
||||
/// NOTE: You must follow the rules of hooks when calling this method.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use dioxus::prelude::*;
|
||||
/// # async fn sleep(delay: u32) {}
|
||||
///
|
||||
/// #[component]
|
||||
/// fn Comp(count: u32) -> Element {
|
||||
/// // Because the resource subscribes to `delay` by adding it as a dependency, the memo will rerun every time `count` changes.
|
||||
/// let new_count = use_memo(move || async move {
|
||||
/// count + 1
|
||||
/// })
|
||||
/// .use_dependencies((&count,));
|
||||
///
|
||||
/// todo!()
|
||||
/// }
|
||||
/// ```
|
||||
pub fn use_dependencies(self, dependency: impl Dependency) -> Self
|
||||
where
|
||||
T: PartialEq,
|
||||
{
|
||||
let mut dependencies_signal = use_hook(|| CopyValue::new(dependency.out()));
|
||||
let changed = { dependency.changed(&*dependencies_signal.read()) };
|
||||
if changed {
|
||||
dependencies_signal.set(dependency.out());
|
||||
self.recompute();
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Readable for Memo<T>
|
||||
|
||||
Reference in new issue
Block a user