mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
feat: add mapping over Option store fields
This commit is contained in:
parent
e8be9e31ff
commit
40292d0896
2 changed files with 81 additions and 1 deletions
|
@ -591,4 +591,65 @@ mod tests {
|
|||
assert_eq!(parent_count.load(Ordering::Relaxed), 2);
|
||||
assert_eq!(inner_count.load(Ordering::Relaxed), 3);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn mapping_over_optional_store_field() {
|
||||
use crate::OptionStoreExt;
|
||||
|
||||
_ = any_spawner::Executor::init_tokio();
|
||||
|
||||
let parent_count = Arc::new(AtomicUsize::new(0));
|
||||
let inner_count = Arc::new(AtomicUsize::new(0));
|
||||
|
||||
let store = Store::new(StructWithOption { opt_field: None });
|
||||
|
||||
Effect::new_sync({
|
||||
let parent_count = Arc::clone(&parent_count);
|
||||
move |prev: Option<()>| {
|
||||
if prev.is_none() {
|
||||
println!("parent: first run");
|
||||
} else {
|
||||
println!("parent: next run");
|
||||
}
|
||||
|
||||
println!(" is_some = {}", store.opt_field().read().is_some());
|
||||
parent_count.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
});
|
||||
Effect::new_sync({
|
||||
let inner_count = Arc::clone(&inner_count);
|
||||
move |prev: Option<()>| {
|
||||
if prev.is_none() {
|
||||
println!("inner: first run");
|
||||
} else {
|
||||
println!("inner: next run");
|
||||
}
|
||||
|
||||
println!(
|
||||
"store inner value length = {:?}",
|
||||
store.opt_field().map(|inner| inner.label().read().len())
|
||||
);
|
||||
inner_count.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
});
|
||||
|
||||
tick().await;
|
||||
assert_eq!(parent_count.load(Ordering::Relaxed), 1);
|
||||
assert_eq!(inner_count.load(Ordering::Relaxed), 1);
|
||||
|
||||
store.opt_field().set(Some(Todo {
|
||||
label: "First Todo".to_owned(),
|
||||
completed: false,
|
||||
}));
|
||||
tick().await;
|
||||
assert_eq!(parent_count.load(Ordering::Relaxed), 2);
|
||||
assert_eq!(inner_count.load(Ordering::Relaxed), 2);
|
||||
|
||||
println!("\nUpdating label only");
|
||||
store.opt_field().unwrap().label().write().push_str("!!!");
|
||||
|
||||
tick().await;
|
||||
assert_eq!(parent_count.load(Ordering::Relaxed), 2);
|
||||
assert_eq!(inner_count.load(Ordering::Relaxed), 3);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use crate::{StoreField, Subfield};
|
||||
use reactive_graph::traits::Read;
|
||||
use std::ops::Deref;
|
||||
|
||||
pub trait OptionStoreExt
|
||||
where
|
||||
|
@ -7,11 +9,17 @@ where
|
|||
type Output;
|
||||
|
||||
fn unwrap(self) -> Subfield<Self, Option<Self::Output>, Self::Output>;
|
||||
|
||||
fn map<U>(
|
||||
self,
|
||||
map_fn: impl FnOnce(Subfield<Self, Option<Self::Output>, Self::Output>) -> U,
|
||||
) -> Option<U>;
|
||||
}
|
||||
|
||||
impl<T, S> OptionStoreExt for S
|
||||
where
|
||||
S: StoreField<Value = Option<T>>,
|
||||
S: StoreField<Value = Option<T>> + Read,
|
||||
<S as Read>::Value: Deref<Target = Option<T>>,
|
||||
{
|
||||
type Output = T;
|
||||
|
||||
|
@ -23,4 +31,15 @@ where
|
|||
|t| t.as_mut().unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
fn map<U>(
|
||||
self,
|
||||
map_fn: impl FnOnce(Subfield<S, Option<T>, T>) -> U,
|
||||
) -> Option<U> {
|
||||
if self.read().is_some() {
|
||||
Some(map_fn(self.unwrap()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue