mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
fix: correctly rebuild reactive attributes to avoid stale signals
This commit is contained in:
parent
2a236e043a
commit
309a3d504a
3 changed files with 146 additions and 44 deletions
|
@ -1,4 +1,4 @@
|
|||
use super::{ReactiveFunction, RenderEffectState, SharedReactiveFunction};
|
||||
use super::{ReactiveFunction, RenderEffect, SharedReactiveFunction};
|
||||
use crate::{html::class::IntoClass, renderer::DomRenderer};
|
||||
use reactive_graph::{effect::RenderEffect, signal::guards::ReadGuard};
|
||||
use std::{
|
||||
|
@ -14,7 +14,7 @@ where
|
|||
C::State: 'static,
|
||||
R: DomRenderer,
|
||||
{
|
||||
type State = RenderEffectState<C::State>;
|
||||
type State = RenderEffect<C::State>;
|
||||
type Cloneable = SharedReactiveFunction<C>;
|
||||
type CloneableOwned = SharedReactiveFunction<C>;
|
||||
|
||||
|
@ -60,9 +60,7 @@ where
|
|||
}
|
||||
|
||||
fn rebuild(mut self, state: &mut Self::State) {
|
||||
let prev_effect = std::mem::take(&mut state.0);
|
||||
let prev_value = prev_effect.as_ref().and_then(|e| e.take_value());
|
||||
drop(prev_effect);
|
||||
let prev_value = state.take_value();
|
||||
*state = RenderEffect::new_with_value(
|
||||
move |prev| {
|
||||
let value = self.invoke();
|
||||
|
@ -70,12 +68,11 @@ where
|
|||
value.rebuild(&mut state);
|
||||
state
|
||||
} else {
|
||||
todo!()
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
prev_value,
|
||||
)
|
||||
.into();
|
||||
);
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
|
@ -93,7 +90,7 @@ where
|
|||
T: Borrow<bool> + 'static,
|
||||
R: DomRenderer,
|
||||
{
|
||||
type State = RenderEffectState<(R::ClassList, bool)>;
|
||||
type State = RenderEffect<(R::ClassList, bool)>;
|
||||
type Cloneable = (&'static str, SharedReactiveFunction<T>);
|
||||
type CloneableOwned = (&'static str, SharedReactiveFunction<T>);
|
||||
|
||||
|
@ -159,8 +156,30 @@ where
|
|||
.into()
|
||||
}
|
||||
|
||||
fn rebuild(self, _state: &mut Self::State) {
|
||||
// TODO rebuild?
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
let (name, mut f) = self;
|
||||
let prev_value = state.take_value();
|
||||
*state = RenderEffect::new_with_value(
|
||||
move |prev| {
|
||||
let include = *f.invoke().borrow();
|
||||
match prev {
|
||||
Some((class_list, prev)) => {
|
||||
if include {
|
||||
if !prev {
|
||||
R::add_class(&class_list, name);
|
||||
}
|
||||
} else if prev {
|
||||
R::remove_class(&class_list, name);
|
||||
}
|
||||
(class_list.clone(), include)
|
||||
}
|
||||
None => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
},
|
||||
prev_value,
|
||||
);
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
|
@ -178,7 +197,7 @@ where
|
|||
T: Borrow<bool> + 'static,
|
||||
R: DomRenderer,
|
||||
{
|
||||
type State = RenderEffectState<(R::ClassList, bool)>;
|
||||
type State = RenderEffect<(R::ClassList, bool)>;
|
||||
type Cloneable = (Vec<Cow<'static, str>>, SharedReactiveFunction<T>);
|
||||
type CloneableOwned = (Vec<Cow<'static, str>>, SharedReactiveFunction<T>);
|
||||
|
||||
|
@ -255,8 +274,35 @@ where
|
|||
.into()
|
||||
}
|
||||
|
||||
fn rebuild(self, _state: &mut Self::State) {
|
||||
// TODO rebuild?
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
let (names, mut f) = self;
|
||||
let prev_value = state.take_value();
|
||||
|
||||
*state = RenderEffect::new_with_value(
|
||||
move |prev: Option<(R::ClassList, bool)>| {
|
||||
let include = *f.invoke().borrow();
|
||||
match prev {
|
||||
Some((class_list, prev)) => {
|
||||
if include {
|
||||
for name in &names {
|
||||
if !prev {
|
||||
R::add_class(&class_list, name);
|
||||
}
|
||||
}
|
||||
} else if prev {
|
||||
for name in &names {
|
||||
R::remove_class(&class_list, name);
|
||||
}
|
||||
}
|
||||
(class_list.clone(), include)
|
||||
}
|
||||
None => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
},
|
||||
prev_value,
|
||||
);
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
|
@ -375,7 +421,7 @@ mod stable {
|
|||
C::State: 'static,
|
||||
R: DomRenderer,
|
||||
{
|
||||
type State = RenderEffectState<C::State>;
|
||||
type State = RenderEffect<C::State>;
|
||||
type Cloneable = Self;
|
||||
type CloneableOwned = Self;
|
||||
|
||||
|
@ -399,8 +445,8 @@ mod stable {
|
|||
(move || self.get()).build(el)
|
||||
}
|
||||
|
||||
fn rebuild(self, _state: &mut Self::State) {
|
||||
// TODO rebuild here?
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
(move || self.get()).rebuild(state)
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
|
@ -416,7 +462,7 @@ mod stable {
|
|||
where
|
||||
R: DomRenderer,
|
||||
{
|
||||
type State = RenderEffectState<(R::ClassList, bool)>;
|
||||
type State = RenderEffect<(R::ClassList, bool)>;
|
||||
type Cloneable = Self;
|
||||
type CloneableOwned = Self;
|
||||
|
||||
|
@ -446,8 +492,11 @@ mod stable {
|
|||
IntoClass::<R>::build((self.0, move || self.1.get()), el)
|
||||
}
|
||||
|
||||
fn rebuild(self, _state: &mut Self::State) {
|
||||
// TODO rebuild here?
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
IntoClass::<R>::rebuild(
|
||||
(self.0, move || self.1.get()),
|
||||
state,
|
||||
)
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
|
@ -469,7 +518,7 @@ mod stable {
|
|||
C::State: 'static,
|
||||
R: DomRenderer,
|
||||
{
|
||||
type State = RenderEffectState<C::State>;
|
||||
type State = RenderEffect<C::State>;
|
||||
type Cloneable = Self;
|
||||
type CloneableOwned = Self;
|
||||
|
||||
|
@ -493,8 +542,8 @@ mod stable {
|
|||
(move || self.get()).build(el)
|
||||
}
|
||||
|
||||
fn rebuild(self, _state: &mut Self::State) {
|
||||
// TODO rebuild here?
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
(move || self.get()).rebuild(state)
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
|
@ -510,7 +559,7 @@ mod stable {
|
|||
where
|
||||
R: DomRenderer,
|
||||
{
|
||||
type State = RenderEffectState<(R::ClassList, bool)>;
|
||||
type State = RenderEffect<(R::ClassList, bool)>;
|
||||
type Cloneable = Self;
|
||||
type CloneableOwned = Self;
|
||||
|
||||
|
@ -540,8 +589,11 @@ mod stable {
|
|||
IntoClass::<R>::build((self.0, move || self.1.get()), el)
|
||||
}
|
||||
|
||||
fn rebuild(self, _state: &mut Self::State) {
|
||||
// TODO rebuild here?
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
IntoClass::<R>::rebuild(
|
||||
(self.0, move || self.1.get()),
|
||||
state,
|
||||
)
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
|
@ -555,7 +607,7 @@ mod stable {
|
|||
};
|
||||
}
|
||||
|
||||
use super::RenderEffectState;
|
||||
use super::RenderEffect;
|
||||
use crate::{html::class::IntoClass, renderer::DomRenderer};
|
||||
use reactive_graph::{
|
||||
computed::{ArcMemo, Memo},
|
||||
|
|
|
@ -57,8 +57,21 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
fn rebuild(self, _state: &mut Self::State, _key: &str) {
|
||||
// TODO rebuild
|
||||
fn rebuild(mut self, state: &mut Self::State, key: &str) {
|
||||
let prev_value = state.take_value();
|
||||
let key = key.to_owned();
|
||||
*state = RenderEffect::new_with_value(
|
||||
move |prev| {
|
||||
let value = self.invoke();
|
||||
if let Some(mut state) = prev {
|
||||
value.rebuild(&mut state, &key);
|
||||
state
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
prev_value,
|
||||
);
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
|
@ -112,8 +125,8 @@ mod stable {
|
|||
(move || self.get()).build(el, key)
|
||||
}
|
||||
|
||||
fn rebuild(self, _state: &mut Self::State, _key: &str) {
|
||||
// TODO rebuild
|
||||
fn rebuild(self, state: &mut Self::State, key: &str) {
|
||||
(move || self.get()).rebuild(state, key)
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
|
@ -155,8 +168,8 @@ mod stable {
|
|||
(move || self.get()).build(el, key)
|
||||
}
|
||||
|
||||
fn rebuild(self, _state: &mut Self::State, _key: &str) {
|
||||
// TODO rebuild
|
||||
fn rebuild(self, state: &mut Self::State, key: &str) {
|
||||
(move || self.get()).rebuild(state, key)
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
|
|
|
@ -74,8 +74,25 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
fn rebuild(self, _state: &mut Self::State) {
|
||||
// TODO rebuild
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
let (name, mut f) = self;
|
||||
let prev_value = state.take_value();
|
||||
*state = RenderEffect::new_with_value(
|
||||
move |prev| {
|
||||
let value = f.invoke().into();
|
||||
if let Some(mut state) = prev {
|
||||
let (style, prev) = &mut state;
|
||||
if &value != prev {
|
||||
R::set_css_property(style, name, &value);
|
||||
}
|
||||
*prev = value;
|
||||
state
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
prev_value,
|
||||
);
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
|
@ -133,7 +150,21 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
fn rebuild(self, _state: &mut Self::State) {}
|
||||
fn rebuild(mut self, state: &mut Self::State) {
|
||||
let prev_value = state.take_value();
|
||||
*state = RenderEffect::new_with_value(
|
||||
move |prev| {
|
||||
let value = self.invoke();
|
||||
if let Some(mut state) = prev {
|
||||
value.rebuild(&mut state);
|
||||
state
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
prev_value,
|
||||
);
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
self.into_shared()
|
||||
|
@ -174,8 +205,8 @@ mod stable {
|
|||
(move || self.get()).build(el)
|
||||
}
|
||||
|
||||
fn rebuild(self, _state: &mut Self::State) {
|
||||
// TODO rebuild here?
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
(move || self.get()).rebuild(el, state)
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
|
@ -218,8 +249,11 @@ mod stable {
|
|||
IntoStyle::<R>::build((self.0, move || self.1.get()), el)
|
||||
}
|
||||
|
||||
fn rebuild(self, _state: &mut Self::State) {
|
||||
// TODO rebuild here?
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
IntoStyle::<R>::rebuild(
|
||||
(self.0, move || self.1.get()),
|
||||
state,
|
||||
)
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
|
@ -261,8 +295,8 @@ mod stable {
|
|||
(move || self.get()).build(el)
|
||||
}
|
||||
|
||||
fn rebuild(self, _state: &mut Self::State) {
|
||||
// TODO rebuild here?
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
(move || self.get()).rebuild(state)
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
|
@ -305,8 +339,11 @@ mod stable {
|
|||
IntoStyle::<R>::build((self.0, move || self.1.get()), el)
|
||||
}
|
||||
|
||||
fn rebuild(self, _state: &mut Self::State) {
|
||||
// TODO rebuild here?
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
IntoStyle::<R>::rebuild(
|
||||
(self.0, move || self.1.get()),
|
||||
state,
|
||||
)
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
|
|
Loading…
Reference in a new issue