signal.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. use std::{
  2. cell::{Ref, RefCell, RefMut},
  3. mem::MaybeUninit,
  4. ops::{Deref, DerefMut},
  5. rc::Rc,
  6. sync::Arc,
  7. };
  8. use dioxus_core::{
  9. prelude::{current_scope_id, has_context, provide_context, schedule_update_any},
  10. ScopeId, ScopeState,
  11. };
  12. use crate::{get_effect_stack, CopyValue, Effect, EffectStack};
  13. /// Creates a new Signal. Signals are a Copy state management solution with automatic dependency tracking.
  14. ///
  15. /// ```rust
  16. /// use dioxus::prelude::*;
  17. /// use dioxus_signals::*;
  18. ///
  19. /// fn App(cx: Scope) -> Element {
  20. /// let mut count = use_signal(cx, || 0);
  21. ///
  22. /// // Because signals have automatic dependency tracking, if you never read them in a component, that component will not be re-rended when the signal is updated.
  23. /// // The app component will never be rerendered in this example.
  24. /// render! { Child { state: count } }
  25. /// }
  26. ///
  27. /// #[component]
  28. /// fn Child(cx: Scope, state: Signal<u32>) -> Element {
  29. /// let state = *state;
  30. ///
  31. /// use_future!(cx, |()| async move {
  32. /// // Because the signal is a Copy type, we can use it in an async block without cloning it.
  33. /// *state.write() += 1;
  34. /// });
  35. ///
  36. /// render! {
  37. /// button {
  38. /// onclick: move |_| *state.write() += 1,
  39. /// "{state}"
  40. /// }
  41. /// }
  42. /// }
  43. /// ```
  44. #[must_use]
  45. pub fn use_signal<T: 'static>(cx: &ScopeState, f: impl FnOnce() -> T) -> Signal<T> {
  46. *cx.use_hook(|| Signal::new(f()))
  47. }
  48. #[derive(Clone)]
  49. struct Unsubscriber {
  50. scope: ScopeId,
  51. subscribers: UnsubscriberArray,
  52. }
  53. type UnsubscriberArray = Rc<RefCell<Vec<Rc<RefCell<Vec<ScopeId>>>>>>;
  54. impl Drop for Unsubscriber {
  55. fn drop(&mut self) {
  56. for subscribers in self.subscribers.borrow().iter() {
  57. subscribers.borrow_mut().retain(|s| *s != self.scope);
  58. }
  59. }
  60. }
  61. fn current_unsubscriber() -> Unsubscriber {
  62. match has_context() {
  63. Some(rt) => rt,
  64. None => {
  65. let owner = Unsubscriber {
  66. scope: current_scope_id().expect("in a virtual dom"),
  67. subscribers: Default::default(),
  68. };
  69. provide_context(owner).expect("in a virtual dom")
  70. }
  71. }
  72. }
  73. pub(crate) struct SignalData<T> {
  74. pub(crate) subscribers: Rc<RefCell<Vec<ScopeId>>>,
  75. pub(crate) effect_subscribers: Rc<RefCell<Vec<Effect>>>,
  76. pub(crate) update_any: Arc<dyn Fn(ScopeId)>,
  77. pub(crate) effect_stack: EffectStack,
  78. pub(crate) value: T,
  79. }
  80. /// Creates a new Signal. Signals are a Copy state management solution with automatic dependency tracking.
  81. ///
  82. /// ```rust
  83. /// use dioxus::prelude::*;
  84. /// use dioxus_signals::*;
  85. ///
  86. /// #[component]
  87. /// fn App(cx: Scope) -> Element {
  88. /// let mut count = use_signal(cx, || 0);
  89. ///
  90. /// // Because signals have automatic dependency tracking, if you never read them in a component, that component will not be re-rended when the signal is updated.
  91. /// // The app component will never be rerendered in this example.
  92. /// render! { Child { state: count } }
  93. /// }
  94. ///
  95. /// #[component]
  96. /// fn Child(cx: Scope, state: Signal<u32>) -> Element {
  97. /// let state = *state;
  98. ///
  99. /// use_future!(cx, |()| async move {
  100. /// // Because the signal is a Copy type, we can use it in an async block without cloning it.
  101. /// *state.write() += 1;
  102. /// });
  103. ///
  104. /// render! {
  105. /// button {
  106. /// onclick: move |_| *state.write() += 1,
  107. /// "{state}"
  108. /// }
  109. /// }
  110. /// }
  111. /// ```
  112. pub struct Signal<T: 'static> {
  113. pub(crate) inner: CopyValue<SignalData<T>>,
  114. }
  115. #[cfg(feature = "serde")]
  116. impl<T: serde::Serialize + 'static> serde::Serialize for Signal<T> {
  117. fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
  118. self.read().serialize(serializer)
  119. }
  120. }
  121. #[cfg(feature = "serde")]
  122. impl<'de, T: serde::Deserialize<'de> + 'static> serde::Deserialize<'de> for Signal<T> {
  123. fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
  124. Ok(Self::new(T::deserialize(deserializer)?))
  125. }
  126. }
  127. impl<T: 'static> Signal<T> {
  128. /// Creates a new Signal. Signals are a Copy state management solution with automatic dependency tracking.
  129. pub fn new(value: T) -> Self {
  130. Self {
  131. inner: CopyValue::new(SignalData {
  132. subscribers: Default::default(),
  133. effect_subscribers: Default::default(),
  134. update_any: schedule_update_any().expect("in a virtual dom"),
  135. value,
  136. effect_stack: get_effect_stack(),
  137. }),
  138. }
  139. }
  140. /// Create a new signal with a custom owner scope. The signal will be dropped when the owner scope is dropped instead of the current scope.
  141. pub fn new_in_scope(value: T, owner: ScopeId) -> Self {
  142. Self {
  143. inner: CopyValue::new_in_scope(
  144. SignalData {
  145. subscribers: Default::default(),
  146. effect_subscribers: Default::default(),
  147. update_any: schedule_update_any().expect("in a virtual dom"),
  148. value,
  149. effect_stack: get_effect_stack(),
  150. },
  151. owner,
  152. ),
  153. }
  154. }
  155. /// Get the scope the signal was created in.
  156. pub fn origin_scope(&self) -> ScopeId {
  157. self.inner.origin_scope()
  158. }
  159. /// Get the current value of the signal. This will subscribe the current scope to the signal.
  160. /// If the signal has been dropped, this will panic.
  161. pub fn read(&self) -> Ref<T> {
  162. let inner = self.inner.read();
  163. if let Some(effect) = inner.effect_stack.current() {
  164. let mut effect_subscribers = inner.effect_subscribers.borrow_mut();
  165. if !effect_subscribers.contains(&effect) {
  166. effect_subscribers.push(effect);
  167. }
  168. } else if let Some(current_scope_id) = current_scope_id() {
  169. // only subscribe if the vdom is rendering
  170. if dioxus_core::vdom_is_rendering() {
  171. tracing::trace!(
  172. "{:?} subscribed to {:?}",
  173. self.inner.value,
  174. current_scope_id
  175. );
  176. let mut subscribers = inner.subscribers.borrow_mut();
  177. if !subscribers.contains(&current_scope_id) {
  178. subscribers.push(current_scope_id);
  179. drop(subscribers);
  180. let unsubscriber = current_unsubscriber();
  181. inner.subscribers.borrow_mut().push(unsubscriber.scope);
  182. }
  183. }
  184. }
  185. Ref::map(inner, |v| &v.value)
  186. }
  187. /// Get a mutable reference to the signal's value.
  188. /// If the signal has been dropped, this will panic.
  189. pub fn write(&self) -> Write<'_, T> {
  190. let inner = self.inner.write();
  191. let borrow = RefMut::map(inner, |v| &mut v.value);
  192. Write {
  193. write: borrow,
  194. signal: SignalSubscriberDrop { signal: *self },
  195. }
  196. }
  197. fn update_subscribers(&self) {
  198. {
  199. let inner = self.inner.read();
  200. for &scope_id in &*inner.subscribers.borrow() {
  201. tracing::trace!(
  202. "Write on {:?} triggered update on {:?}",
  203. self.inner.value,
  204. scope_id
  205. );
  206. (inner.update_any)(scope_id);
  207. }
  208. }
  209. let subscribers = {
  210. let self_read = self.inner.read();
  211. let mut effects = self_read.effect_subscribers.borrow_mut();
  212. std::mem::take(&mut *effects)
  213. };
  214. for effect in subscribers {
  215. tracing::trace!(
  216. "Write on {:?} triggered effect {:?}",
  217. self.inner.value,
  218. effect
  219. );
  220. effect.try_run();
  221. }
  222. }
  223. /// Set the value of the signal. This will trigger an update on all subscribers.
  224. pub fn set(&self, value: T) {
  225. *self.write() = value;
  226. }
  227. /// Run a closure with a reference to the signal's value.
  228. /// If the signal has been dropped, this will panic.
  229. pub fn with<O>(&self, f: impl FnOnce(&T) -> O) -> O {
  230. let write = self.read();
  231. f(&*write)
  232. }
  233. /// Run a closure with a mutable reference to the signal's value.
  234. /// If the signal has been dropped, this will panic.
  235. pub fn with_mut<O>(&self, f: impl FnOnce(&mut T) -> O) -> O {
  236. let mut write = self.write();
  237. f(&mut *write)
  238. }
  239. }
  240. impl<T: Clone + 'static> Signal<T> {
  241. /// Get the current value of the signal. This will subscribe the current scope to the signal.
  242. /// If the signal has been dropped, this will panic.
  243. pub fn value(&self) -> T {
  244. self.read().clone()
  245. }
  246. }
  247. impl Signal<bool> {
  248. /// Invert the boolean value of the signal. This will trigger an update on all subscribers.
  249. pub fn toggle(&self) {
  250. self.set(!self.value());
  251. }
  252. }
  253. impl<T: 'static> PartialEq for Signal<T> {
  254. fn eq(&self, other: &Self) -> bool {
  255. self.inner == other.inner
  256. }
  257. }
  258. impl<T> Deref for Signal<T> {
  259. type Target = dyn Fn() -> Ref<'static, T>;
  260. fn deref(&self) -> &Self::Target {
  261. // https://github.com/dtolnay/case-studies/tree/master/callable-types
  262. // First we create a closure that captures something with the Same in memory layout as Self (MaybeUninit<Self>).
  263. let uninit_callable = MaybeUninit::<Self>::uninit();
  264. // Then move that value into the closure. We assume that the closure now has a in memory layout of Self.
  265. let uninit_closure = move || Self::read(unsafe { &*uninit_callable.as_ptr() });
  266. // Check that the size of the closure is the same as the size of Self in case the compiler changed the layout of the closure.
  267. let size_of_closure = std::mem::size_of_val(&uninit_closure);
  268. assert_eq!(size_of_closure, std::mem::size_of::<Self>());
  269. // Then cast the lifetime of the closure to the lifetime of &self.
  270. fn cast_lifetime<'a, T>(_a: &T, b: &'a T) -> &'a T {
  271. b
  272. }
  273. let reference_to_closure = cast_lifetime(
  274. {
  275. // The real closure that we will never use.
  276. &uninit_closure
  277. },
  278. // We transmute self into a reference to the closure. This is safe because we know that the closure has the same memory layout as Self so &Closure == &Self.
  279. unsafe { std::mem::transmute(self) },
  280. );
  281. // Cast the closure to a trait object.
  282. reference_to_closure as &Self::Target
  283. }
  284. }
  285. struct SignalSubscriberDrop<T: 'static> {
  286. signal: Signal<T>,
  287. }
  288. impl<T: 'static> Drop for SignalSubscriberDrop<T> {
  289. fn drop(&mut self) {
  290. self.signal.update_subscribers();
  291. }
  292. }
  293. /// A mutable reference to a signal's value.
  294. pub struct Write<'a, T: 'static, I: 'static = T> {
  295. write: RefMut<'a, T>,
  296. signal: SignalSubscriberDrop<I>,
  297. }
  298. impl<'a, T: 'static, I: 'static> Write<'a, T, I> {
  299. /// Map the mutable reference to the signal's value to a new type.
  300. pub fn map<O>(myself: Self, f: impl FnOnce(&mut T) -> &mut O) -> Write<'a, O, I> {
  301. let Self { write, signal } = myself;
  302. Write {
  303. write: RefMut::map(write, f),
  304. signal,
  305. }
  306. }
  307. /// Try to map the mutable reference to the signal's value to a new type
  308. pub fn filter_map<O>(
  309. myself: Self,
  310. f: impl FnOnce(&mut T) -> Option<&mut O>,
  311. ) -> Option<Write<'a, O, I>> {
  312. let Self { write, signal } = myself;
  313. let write = RefMut::filter_map(write, f).ok();
  314. write.map(|write| Write { write, signal })
  315. }
  316. }
  317. impl<'a, T: 'static, I: 'static> Deref for Write<'a, T, I> {
  318. type Target = T;
  319. fn deref(&self) -> &Self::Target {
  320. &self.write
  321. }
  322. }
  323. impl<T, I> DerefMut for Write<'_, T, I> {
  324. fn deref_mut(&mut self) -> &mut Self::Target {
  325. &mut self.write
  326. }
  327. }
  328. /// A signal that can only be read from.
  329. pub struct ReadOnlySignal<T: 'static> {
  330. inner: Signal<T>,
  331. }
  332. impl<T: 'static> ReadOnlySignal<T> {
  333. /// Create a new read-only signal.
  334. pub fn new(signal: Signal<T>) -> Self {
  335. Self { inner: signal }
  336. }
  337. /// Get the scope that the signal was created in.
  338. pub fn origin_scope(&self) -> ScopeId {
  339. self.inner.origin_scope()
  340. }
  341. /// Get the current value of the signal. This will subscribe the current scope to the signal.
  342. pub fn read(&self) -> Ref<T> {
  343. self.inner.read()
  344. }
  345. /// Run a closure with a reference to the signal's value.
  346. pub fn with<O>(&self, f: impl FnOnce(&T) -> O) -> O {
  347. self.inner.with(f)
  348. }
  349. }
  350. impl<T: Clone + 'static> ReadOnlySignal<T> {
  351. /// Get the current value of the signal. This will subscribe the current scope to the signal.
  352. pub fn value(&self) -> T {
  353. self.read().clone()
  354. }
  355. }
  356. impl<T: 'static> PartialEq for ReadOnlySignal<T> {
  357. fn eq(&self, other: &Self) -> bool {
  358. self.inner == other.inner
  359. }
  360. }
  361. impl<T> Deref for ReadOnlySignal<T> {
  362. type Target = dyn Fn() -> Ref<'static, T>;
  363. fn deref(&self) -> &Self::Target {
  364. // https://github.com/dtolnay/case-studies/tree/master/callable-types
  365. // First we create a closure that captures something with the Same in memory layout as Self (MaybeUninit<Self>).
  366. let uninit_callable = MaybeUninit::<Self>::uninit();
  367. // Then move that value into the closure. We assume that the closure now has a in memory layout of Self.
  368. let uninit_closure = move || Self::read(unsafe { &*uninit_callable.as_ptr() });
  369. // Check that the size of the closure is the same as the size of Self in case the compiler changed the layout of the closure.
  370. let size_of_closure = std::mem::size_of_val(&uninit_closure);
  371. assert_eq!(size_of_closure, std::mem::size_of::<Self>());
  372. // Then cast the lifetime of the closure to the lifetime of &self.
  373. fn cast_lifetime<'a, T>(_a: &T, b: &'a T) -> &'a T {
  374. b
  375. }
  376. let reference_to_closure = cast_lifetime(
  377. {
  378. // The real closure that we will never use.
  379. &uninit_closure
  380. },
  381. // We transmute self into a reference to the closure. This is safe because we know that the closure has the same memory layout as Self so &Closure == &Self.
  382. unsafe { std::mem::transmute(self) },
  383. );
  384. // Cast the closure to a trait object.
  385. reference_to_closure as &Self::Target
  386. }
  387. }