Compare commits

..

2 Commits

Author SHA1 Message Date
Greg Johnston
0aafcc3947 chore: warning 2025-12-28 21:45:03 -05:00
Greg Johnston
5c2482fadc fix: preserve existing attributes when rebuilding AnyViewWithAttrs
(closes #4512)
2025-12-28 20:26:08 -05:00
3 changed files with 36 additions and 87 deletions

View File

@@ -140,20 +140,13 @@ where
}
fn track_field(&self) {
let mut full_path = self.path().into_iter().collect::<StorePath>();
let inner = self
.inner
.get_trigger(self.inner.path().into_iter().collect());
inner.this.track();
let trigger = self.get_trigger(self.path().into_iter().collect());
trigger.this.track();
trigger.children.track();
// tracks `this` for all ancestors: i.e., it will track any change that is made
// directly to one of its ancestors, but not a change made to a *child* of an ancestor
// (which would end up with every subfield tracking its own siblings, because they are
// children of its parent)
while !full_path.is_empty() {
full_path.pop();
let inner = self.get_trigger(full_path.clone());
inner.this.track();
}
}
}

View File

@@ -57,11 +57,11 @@
//! # if false { // don't run effect in doctests
//! Effect::new(move |_| {
//! // you can access individual store fields with a getter
//! println!("user: {:?}", &*store.user().read());
//! println!("todos: {:?}", &*store.todos().read());
//! });
//! # }
//!
//! // won't notify the effect that listens to `user`
//! // won't notify the effect that listens to `todos`
//! store.todos().write().push(Todo {
//! label: "Test".to_string(),
//! completed: false,

View File

@@ -23,32 +23,14 @@ pub fn keyed<T, I, K, KF, VF, VFS, V>(
) -> Keyed<T, I, K, KF, VF, VFS, V>
where
I: IntoIterator<Item = T>,
K: Eq + Hash + SerializableKey + 'static,
K: Eq + Hash + 'static,
KF: Fn(&T) -> K,
V: Render,
VF: Fn(usize, T) -> (VFS, V),
VFS: Fn(usize),
{
Keyed {
#[cfg(not(feature = "ssr"))]
items: Some(items),
#[cfg(feature = "ssr")]
items: None,
#[cfg(feature = "ssr")]
ssr_items: items
.into_iter()
.enumerate()
.map(|(i, t)| {
let key = if cfg!(feature = "islands") {
let key = (key_fn)(&t);
key.ser_key()
} else {
String::new()
};
let (_, view) = (view_fn)(i, t);
(key, view)
})
.collect::<Vec<_>>(),
items,
key_fn,
view_fn,
}
@@ -63,9 +45,7 @@ where
VF: Fn(usize, T) -> (VFS, V),
VFS: Fn(usize),
{
items: Option<I>,
#[cfg(feature = "ssr")]
ssr_items: Vec<(String, V)>,
items: I,
key_fn: KF,
view_fn: VF,
}
@@ -126,13 +106,14 @@ where
VFS: Fn(usize),
{
type State = KeyedState<K, VFS, V>;
// TODO fallible state and try_build()/try_rebuild() here
fn build(self) -> Self::State {
let items = self.items.into_iter().flatten();
let items = self.items.into_iter();
let (capacity, _) = items.size_hint();
let mut hashed_items =
FxIndexSet::with_capacity_and_hasher(capacity, Default::default());
let mut rendered_items = Vec::with_capacity(capacity);
let mut rendered_items = Vec::new();
for (index, item) in items.enumerate() {
hashed_items.insert((self.key_fn)(&item));
let (set_index, view) = (self.view_fn)(index, item);
@@ -153,7 +134,7 @@ where
hashed_items,
ref mut rendered_items,
} = state;
let new_items = self.items.into_iter().flatten();
let new_items = self.items.into_iter();
let (capacity, _) = new_items.size_hint();
let mut new_hashed_items =
FxIndexSet::with_capacity_and_hasher(capacity, Default::default());
@@ -217,8 +198,6 @@ where
{
let Keyed {
items,
#[cfg(feature = "ssr")]
ssr_items,
key_fn,
view_fn,
} = self;
@@ -226,11 +205,6 @@ where
Keyed {
items,
key_fn,
#[cfg(feature = "ssr")]
ssr_items: ssr_items
.into_iter()
.map(|(k, v)| (k, v.add_any_attr(attr.clone())))
.collect(),
view_fn: Box::new(move |index, item| {
let (index, view) = view_fn(index, item);
(index, view.add_any_attr(attr.clone()))
@@ -255,39 +229,21 @@ where
const MIN_LENGTH: usize = 0;
fn dry_resolve(&mut self) {
#[cfg(feature = "ssr")]
for view in &mut self.ssr_items {
view.dry_resolve();
}
// TODO...
}
async fn resolve(self) -> Self::AsyncOutput {
#[cfg(feature = "ssr")]
{
futures::future::join_all(
self.ssr_items.into_iter().map(|(_, view)| view.resolve()),
)
.await
.into_iter()
.collect::<Vec<_>>()
}
#[cfg(not(feature = "ssr"))]
{
futures::future::join_all(
self.items.into_iter().flatten().enumerate().map(
|(index, item)| {
let (_, view) = (self.view_fn)(index, item);
view.resolve()
},
),
)
.await
.into_iter()
.collect::<Vec<_>>()
}
futures::future::join_all(self.items.into_iter().enumerate().map(
|(index, item)| {
let (_, view) = (self.view_fn)(index, item);
view.resolve()
},
))
.await
.into_iter()
.collect::<Vec<_>>()
}
#[allow(unused)]
fn to_html_with_buf(
self,
buf: &mut String,
@@ -299,9 +255,8 @@ where
if mark_branches && escape {
buf.open_branch("for");
}
#[cfg(feature = "ssr")]
for item in self.ssr_items {
for (index, item) in self.items.into_iter().enumerate() {
let (_, item) = (self.view_fn)(index, item);
if mark_branches && escape {
buf.open_branch("item");
}
@@ -323,7 +278,6 @@ where
buf.push_str("<!>");
}
#[allow(unused)]
fn to_html_async_with_buf<const OUT_OF_ORDER: bool>(
self,
buf: &mut StreamBuilder,
@@ -335,10 +289,13 @@ where
if mark_branches && escape {
buf.open_branch("for");
}
#[cfg(feature = "ssr")]
for (key, item) in self.ssr_items {
let branch_name = mark_branches.then(|| format!("item-{key}"));
for (index, item) in self.items.into_iter().enumerate() {
let branch_name = mark_branches.then(|| {
let key = (self.key_fn)(&item);
let key = key.ser_key();
format!("item-{key}")
});
let (_, item) = (self.view_fn)(index, item);
if mark_branches && escape {
buf.open_branch(branch_name.as_ref().unwrap());
}
@@ -354,7 +311,6 @@ where
}
*position = Position::NextChild;
}
if mark_branches && escape {
buf.close_branch("for");
}
@@ -378,11 +334,11 @@ where
.expect("parent of keyed list should be an element");
// build list
let items = self.items.into_iter().flatten();
let items = self.items.into_iter();
let (capacity, _) = items.size_hint();
let mut hashed_items =
FxIndexSet::with_capacity_and_hasher(capacity, Default::default());
let mut rendered_items = Vec::with_capacity(capacity);
let mut rendered_items = Vec::new();
for (index, item) in items.enumerate() {
hashed_items.insert((self.key_fn)(&item));
let (set_index, view) = (self.view_fn)(index, item);
@@ -417,11 +373,11 @@ where
.expect("parent of keyed list should be an element");
// build list
let items = self.items.into_iter().flatten();
let items = self.items.into_iter();
let (capacity, _) = items.size_hint();
let mut hashed_items =
FxIndexSet::with_capacity_and_hasher(capacity, Default::default());
let mut rendered_items = Vec::with_capacity(capacity);
let mut rendered_items = Vec::new();
for (index, item) in items.enumerate() {
hashed_items.insert((self.key_fn)(&item));
let (set_index, view) = (self.view_fn)(index, item);