add a way to subscribe to a dependency tuple for the use_resource hook

This commit is contained in:
Evan Almloff committed 2024-03-12 16:50:03 -05:00
1 parent 41809f9a1b
commit 2bbc609082
3 files changed
+73 -40

No files matched your search

+5 -5
View File
@@ -1,7 +1,7 @@
/// 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;
type Out: Clone + PartialEq + 'static;
/// Returns the output of the dependency.
fn out(&self) -> Self::Out;
/// Returns true if the dependency has changed.
@@ -16,10 +16,10 @@ impl Dependency for () {
}
/// A dependency is a trait that can be used to determine if a effect or selector should be re-run.
pub trait Dep: 'static + PartialEq + Clone {}
impl<T> Dep for T where T: 'static + PartialEq + Clone {}
pub trait DependencyElement: 'static + PartialEq + Clone {}
impl<T> DependencyElement for T where T: 'static + PartialEq + Clone {}
impl<A: Dep> Dependency for &A {
impl<A: DependencyElement> Dependency for &A {
type Out = A;
fn out(&self) -> Self::Out {
(*self).clone()
@@ -33,7 +33,7 @@ macro_rules! impl_dep {
impl< $($el),* > Dependency for ($(&$el,)*)
where
$(
$el: Dep
$el: DependencyElement
),*
{
type Out = ($($el,)*);
+41 -1
View File
@@ -1,6 +1,6 @@
#![allow(missing_docs)]
use crate::{use_callback, use_signal, UseCallback};
use crate::{dependency, use_callback, use_signal, UseCallback};
use dioxus_core::prelude::*;
use dioxus_core::{
prelude::{spawn, use_hook},
@@ -125,6 +125,46 @@ pub enum UseResourceState {
}
impl<T> Resource<T> {
/// Adds an explicit dependency to the resource. If the dependency changes, the resource's future 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(delay: u32) -> Element {
/// // Because the resource subscribes to `delay` by adding it as a dependency, the resource's future will rerun every time `delay` changes.
/// let current_weather = use_resource(move || async move {
/// sleep(delay).await;
/// "Sunny"
/// })
/// .use_dependencies((&delay,));
///
/// rsx! {
/// // the value of the resource can be polled to
/// // conditionally render elements based off if it's future
/// // finished (Some(Ok(_)), errored Some(Err(_)),
/// // or is still running (None)
/// match &*current_weather.read_unchecked() {
/// Some(weather) => rsx! { "{weather}" },
/// None => rsx! { p { "Loading..." } }
/// }
/// }
/// }
/// ```
pub fn use_dependencies(self, dependency: impl dependency::Dependency) -> Self {
let mut dependencies_signal = use_signal(|| dependency.out());
let changed = { dependency.changed(&*dependencies_signal.read()) };
if changed {
dependencies_signal.set(dependency.out());
}
self
}
/// Restart the resource's future.
///
/// Will not cancel the previous future, but will ignore any values that it