diff --git a/reactive_stores/src/keyed.rs b/reactive_stores/src/keyed.rs index ea27b0484..5312bcc0d 100644 --- a/reactive_stores/src/keyed.rs +++ b/reactive_stores/src/keyed.rs @@ -176,6 +176,7 @@ where { inner: KeyedSubfield, guard: Option, + untracked: bool, } impl Deref @@ -227,6 +228,7 @@ where K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static, { fn untrack(&mut self) { + self.untracked = true; if let Some(inner) = self.guard.as_mut() { inner.untrack(); } @@ -251,7 +253,10 @@ where // now that the write lock is release, we can get a read lock to refresh this keyed field // based on the new value self.inner.update_keys(); - self.inner.notify(); + + if !self.untracked { + self.inner.notify(); + } // reactive updates happen on the next tick } @@ -344,6 +349,7 @@ where Some(KeyedSubfieldWriteGuard { inner: self.clone(), guard: Some(guard), + untracked: false, }) } @@ -355,6 +361,7 @@ where Some(KeyedSubfieldWriteGuard { inner: self.clone(), guard: Some(guard), + untracked: true, }) } } @@ -879,4 +886,41 @@ mod tests { assert_eq!(b_count.load(Ordering::Relaxed), 1); assert_eq!(c_count.load(Ordering::Relaxed), 1); } + + #[tokio::test] + async fn untracked_write_on_keyed_subfield_shouldnt_notify() { + _ = any_spawner::Executor::init_tokio(); + + let store = Store::new(data()); + assert_eq!(store.read_untracked().todos.len(), 3); + + // create an effect to read from the keyed subfield + let todos_count = Arc::new(AtomicUsize::new(0)); + Effect::new_sync({ + let todos_count = Arc::clone(&todos_count); + move || { + store.todos().track(); + todos_count.fetch_add(1, Ordering::Relaxed); + } + }); + + tick().await; + assert_eq!(todos_count.load(Ordering::Relaxed), 1); + + // writing to keyed subfield notifies the iterator + store.todos().write().push(Todo { + id: 13, + label: "D".into(), + }); + tick().await; + assert_eq!(todos_count.load(Ordering::Relaxed), 2); + + // but an untracked write doesn't + store.todos().write_untracked().push(Todo { + id: 14, + label: "E".into(), + }); + tick().await; + assert_eq!(todos_count.load(Ordering::Relaxed), 2); + } }