Compare commits

...

2 Commits
3872 ... 3704v2

Author SHA1 Message Date
Greg Johnston
ea3d772eb7 fix: ensure that store subfield mutations notify from the root down (closes #3704) 2025-03-14 17:50:42 -04:00
Zak Stucke
2a19515c41 Allow LocalResource sync methods to be used outside Suspense 2025-03-13 10:24:37 +00:00
2 changed files with 14 additions and 12 deletions

View File

@@ -172,12 +172,6 @@ where
fn try_read_untracked(&self) -> Option<Self::Value> {
if let Some(mut notifier) = use_context::<LocalResourceNotifier>() {
notifier.notify();
} else if cfg!(feature = "ssr") {
panic!(
"Reading from a LocalResource outside Suspense in `ssr` mode \
will cause the response to hang, because LocalResources are \
always pending on the server."
);
}
self.data.try_read_untracked()
}
@@ -364,12 +358,6 @@ where
fn try_read_untracked(&self) -> Option<Self::Value> {
if let Some(mut notifier) = use_context::<LocalResourceNotifier>() {
notifier.notify();
} else if cfg!(feature = "ssr") {
panic!(
"Reading from a LocalResource outside Suspense in `ssr` mode \
will cause the response to hang, because LocalResources are \
always pending on the server."
);
}
self.data.try_read_untracked()
}

View File

@@ -100,6 +100,9 @@ where
let mut full_path = self.path().into_iter().collect::<StorePath>();
full_path.pop();
// build a list of triggers, starting with the full path to this node and ending with the root
// this will mean that the root is the final item, and this path is first
let mut triggers = Vec::with_capacity(full_path.len());
triggers.push(trigger.this.clone());
loop {
@@ -110,6 +113,17 @@ where
}
full_path.pop();
}
// when the WriteGuard is dropped, each trigger will be notified, in order
// reversing the list will cause the triggers to be notified starting from the root,
// then to each child down to this one
//
// notifying from the root down is important for things like OptionStoreExt::map()/unwrap(),
// where it's really important that any effects that subscribe to .is_some() run before effects
// that subscribe to the inner value, so that the inner effect can be canceled if the outer switches to `None`
// (see https://github.com/leptos-rs/leptos/issues/3704)
triggers.reverse();
let guard = WriteGuard::new(triggers, parent);
Some(MappedMut::new(guard, self.read, self.write))