mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
correct dirty-checking on AsyncDerived
This commit is contained in:
parent
02f76dec35
commit
e13b1561d8
3 changed files with 39 additions and 3 deletions
|
@ -7,6 +7,7 @@ use crate::owner::Sandboxed;
|
|||
use crate::{
|
||||
channel::channel,
|
||||
computed::suspense::SuspenseContext,
|
||||
diagnostics::SpecialNonReactiveFuture,
|
||||
graph::{
|
||||
AnySource, AnySubscriber, ReactiveNode, Source, SourceSet, Subscriber,
|
||||
SubscriberSet, ToAnySource, ToAnySubscriber,
|
||||
|
@ -146,6 +147,7 @@ macro_rules! spawn_derived {
|
|||
}
|
||||
|
||||
// notify reactive subscribers that we're now loading
|
||||
inner.write().or_poisoned().dirty = true;
|
||||
for sub in (&inner.read().or_poisoned().subscribers).into_iter() {
|
||||
sub.mark_check();
|
||||
}
|
||||
|
@ -153,6 +155,7 @@ macro_rules! spawn_derived {
|
|||
// generate and assign new value
|
||||
let new_value = fut.await;
|
||||
*value.write().or_poisoned() = AsyncState::Complete(new_value);
|
||||
inner.write().or_poisoned().dirty = true;
|
||||
ready_tx.send(());
|
||||
|
||||
// notify reactive subscribers that we're not loading any more
|
||||
|
@ -244,7 +247,7 @@ impl<T: Send + Sync + 'static> ReadUntracked for ArcAsyncDerived<T> {
|
|||
if matches!(&*self.value.read().or_poisoned(), AsyncState::Loading)
|
||||
{
|
||||
let handle = suspense_context.task_id();
|
||||
let ready = self.ready();
|
||||
let ready = SpecialNonReactiveFuture::new(self.ready());
|
||||
Executor::spawn(async move {
|
||||
ready.await;
|
||||
drop(handle);
|
||||
|
|
|
@ -48,8 +48,8 @@ impl ReactiveNode for RwLock<ArcAsyncDerivedInner> {
|
|||
guard.dirty = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
drop(guard);
|
||||
|
||||
for source in sources.into_iter().flatten() {
|
||||
if source.update_if_necessary() {
|
||||
return true;
|
||||
|
|
|
@ -16,7 +16,13 @@ pub struct SpecialNonReactiveZone;
|
|||
#[derive(Debug)]
|
||||
pub struct SpecialNonReactiveZoneGuard;
|
||||
|
||||
use std::cell::Cell;
|
||||
use pin_project_lite::pin_project;
|
||||
use std::{
|
||||
cell::Cell,
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
thread_local! {
|
||||
static IS_SPECIAL_ZONE: Cell<bool> = const { Cell::new(false) };
|
||||
|
@ -46,6 +52,33 @@ impl Drop for SpecialNonReactiveZoneGuard {
|
|||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
pub(crate) struct SpecialNonReactiveFuture<Fut> {
|
||||
#[pin]
|
||||
inner: Fut
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> SpecialNonReactiveFuture<Fut> {
|
||||
pub fn new(inner: Fut) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> Future for SpecialNonReactiveFuture<Fut>
|
||||
where
|
||||
Fut: Future,
|
||||
{
|
||||
type Output = Fut::Output;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
#[cfg(debug_assertions)]
|
||||
let _rw = SpecialNonReactiveZone::enter();
|
||||
let this = self.project();
|
||||
this.inner.poll(cx)
|
||||
}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static SUPPRESS_RESOURCE_LOAD: Cell<bool> = const { Cell::new(false) };
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue