use_memo.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. use crate::dependency::Dependency;
  2. use crate::use_signal;
  3. use dioxus_core::prelude::*;
  4. use dioxus_signals::{ReadOnlySignal, Readable, Signal, SignalData};
  5. use dioxus_signals::{Storage, Writable};
  6. /// Creates a new unsync Selector. The selector will be run immediately and whenever any signal it reads changes.
  7. ///
  8. /// Selectors can be used to efficiently compute derived data from signals.
  9. ///
  10. /// ```rust
  11. /// use dioxus::prelude::*;
  12. /// use dioxus_signals::*;
  13. ///
  14. /// fn App() -> Element {
  15. /// let mut count = use_signal(|| 0);
  16. /// let double = use_memo(move || count * 2);
  17. /// count += 1;
  18. /// assert_eq!(double.value(), count * 2);
  19. ///
  20. /// rsx! { "{double}" }
  21. /// }
  22. /// ```
  23. #[track_caller]
  24. pub fn use_memo<R: PartialEq>(f: impl FnMut() -> R + 'static) -> ReadOnlySignal<R> {
  25. use_maybe_sync_memo(f)
  26. }
  27. /// Creates a new Selector that may be sync. The selector will be run immediately and whenever any signal it reads changes.
  28. ///
  29. /// Selectors can be used to efficiently compute derived data from signals.
  30. ///
  31. /// ```rust
  32. /// use dioxus::prelude::*;
  33. /// use dioxus_signals::*;
  34. ///
  35. /// fn App() -> Element {
  36. /// let mut count = use_signal(cx, || 0);
  37. /// let double = use_memo(cx, move || count * 2);
  38. /// count += 1;
  39. /// assert_eq!(double.value(), count * 2);
  40. ///
  41. /// render! { "{double}" }
  42. /// }
  43. /// ```
  44. #[track_caller]
  45. pub fn use_maybe_sync_memo<R: PartialEq, S: Storage<SignalData<R>>>(
  46. f: impl FnMut() -> R + 'static,
  47. ) -> ReadOnlySignal<R, S> {
  48. use_hook(|| Signal::maybe_sync_memo(f))
  49. }
  50. /// Creates a new unsync Selector with some local dependencies. The selector will be run immediately and whenever any signal it reads or any dependencies it tracks changes
  51. ///
  52. /// Selectors can be used to efficiently compute derived data from signals.
  53. ///
  54. /// ```rust
  55. /// use dioxus::prelude::*;
  56. ///
  57. /// fn App() -> Element {
  58. /// let mut local_state = use_state(|| 0);
  59. /// let double = use_memo_with_dependencies(cx, (local_state.get(),), move |(local_state,)| local_state * 2);
  60. /// local_state.set(1);
  61. ///
  62. /// render! { "{double}" }
  63. /// }
  64. /// ```
  65. #[track_caller]
  66. pub fn use_memo_with_dependencies<R: PartialEq, D: Dependency>(
  67. dependencies: D,
  68. f: impl FnMut(D::Out) -> R + 'static,
  69. ) -> ReadOnlySignal<R>
  70. where
  71. D::Out: 'static,
  72. {
  73. use_maybe_sync_selector_with_dependencies(dependencies, f)
  74. }
  75. /// Creates a new Selector that may be sync with some local dependencies. The selector will be run immediately and whenever any signal it reads or any dependencies it tracks changes
  76. ///
  77. /// Selectors can be used to efficiently compute derived data from signals.
  78. ///
  79. /// ```rust
  80. /// use dioxus::prelude::*;
  81. /// use dioxus_signals::*;
  82. ///
  83. /// fn App() -> Element {
  84. /// let mut local_state = use_state(|| 0);
  85. /// let double = use_memo_with_dependencies(cx, (local_state.get(),), move |(local_state,)| local_state * 2);
  86. /// local_state.set(1);
  87. ///
  88. /// render! { "{double}" }
  89. /// }
  90. /// ```
  91. #[track_caller]
  92. pub fn use_maybe_sync_selector_with_dependencies<
  93. R: PartialEq,
  94. D: Dependency,
  95. S: Storage<SignalData<R>>,
  96. >(
  97. dependencies: D,
  98. mut f: impl FnMut(D::Out) -> R + 'static,
  99. ) -> ReadOnlySignal<R, S>
  100. where
  101. D::Out: 'static,
  102. {
  103. let mut dependencies_signal = use_signal(|| dependencies.out());
  104. let selector = use_hook(|| {
  105. Signal::maybe_sync_memo(move || {
  106. let deref = &*dependencies_signal.read();
  107. f(deref.clone())
  108. })
  109. });
  110. let changed = { dependencies.changed(&*dependencies_signal.read()) };
  111. if changed {
  112. dependencies_signal.set(dependencies.out());
  113. }
  114. selector
  115. }