From 06d9b575b725274a76e565f0e821f3d0a2b880ba Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Sat, 20 Jan 2024 23:32:12 -0800 Subject: [PATCH] rename use_selector to use_memo --- examples/all_events.rs | 2 +- examples/calculator.rs | 45 +++++----------- examples/counter.rs | 2 +- examples/global.rs | 6 +-- examples/svg.rs | 2 +- examples/todomvc.rs | 10 ++-- packages/hooks/src/lib.rs | 3 ++ packages/hooks/src/use_sorted.rs | 66 +++++++++++++++++++++++ packages/signals/README.md | 4 +- packages/signals/examples/dependancies.rs | 2 +- packages/signals/examples/selector.rs | 2 +- packages/signals/src/comparer.rs | 6 +-- packages/signals/src/global.rs | 16 +++--- packages/signals/src/impls.rs | 8 +-- packages/signals/src/selector.rs | 26 ++++----- packages/signals/src/signal.rs | 10 ++-- 16 files changed, 130 insertions(+), 80 deletions(-) create mode 100644 packages/hooks/src/use_sorted.rs diff --git a/examples/all_events.rs b/examples/all_events.rs index c11038d60..1e44ee0ff 100644 --- a/examples/all_events.rs +++ b/examples/all_events.rs @@ -25,7 +25,7 @@ const RECT_STYLE: &str = r#" "#; fn app() -> Element { - let mut events = use_signal(|| std::collections::VecDeque::new() as VecDeque>); + let mut events = use_signal(|| VecDeque::new() as VecDeque>); let mut log_event = move |event: Rc| { let mut events = events.write(); diff --git a/examples/calculator.rs b/examples/calculator.rs index 84752fa44..1a75922b9 100644 --- a/examples/calculator.rs +++ b/examples/calculator.rs @@ -27,7 +27,6 @@ fn app() -> Element { if val() == "0" { val.set(String::new()); } - val.write().push_str(num.as_str()); }; @@ -35,15 +34,12 @@ fn app() -> Element { let mut handle_key_down_event = move |evt: KeyboardEvent| match evt.key() { Key::Backspace => { - if !val.cloned().is_empty() { + if !val().is_empty() { val.write().pop(); } } Key::Character(character) => match character.as_str() { - "+" => input_operator("+"), - "-" => input_operator("-"), - "/" => input_operator("/"), - "*" => input_operator("*"), + "+" | "-" | "/" | "*" => input_operator(&character), "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" => input_digit(character), _ => {} }, @@ -72,20 +68,18 @@ fn app() -> Element { button { class: "calculator-key key-sign", onclick: move |_| { - let temp = calc_val(val.cloned().as_str()); - if temp > 0.0 { - val.set(format!("-{temp}")); + let new_val = calc_val(val.cloned().as_str()); + if new_val > 0.0 { + val.set(format!("-{new_val}")); } else { - val.set(format!("{}", temp.abs())); + val.set(format!("{}", new_val.abs())); } }, "±" } button { class: "calculator-key key-percent", - onclick: move |_| { - val.set(format!("{}", calc_val(val.cloned().as_str()) / 100.0)); - }, + onclick: move |_| val.set(format!("{}", calc_val(val.cloned().as_str()) / 100.0)), "%" } } @@ -111,25 +105,12 @@ fn app() -> Element { } } div { class: "operator-keys", - button { - class: "calculator-key key-divide", - onclick: move |_| input_operator("/"), - "÷" - } - button { - class: "calculator-key key-multiply", - onclick: move |_| input_operator("*"), - "×" - } - button { - class: "calculator-key key-subtract", - onclick: move |_| input_operator("-"), - "−" - } - button { - class: "calculator-key key-add", - onclick: move |_| input_operator("+"), - "+" + for (key, class) in [("/", "key-divide"), ("*", "key-multiply"), ("-", "key-subtract"), ("+", "key-add")] { + button { + class: "calculator-key {class}", + onclick: move |_| input_operator(key), + "{key}" + } } button { class: "calculator-key key-equals", diff --git a/examples/counter.rs b/examples/counter.rs index 9efa9d26f..81ef687e2 100644 --- a/examples/counter.rs +++ b/examples/counter.rs @@ -9,7 +9,7 @@ fn main() { fn app() -> Element { let mut counters = use_signal(|| vec![0, 0, 0]); - let sum = use_selector(move || counters.read().iter().copied().sum::()); + let sum = use_memo(move || counters.read().iter().copied().sum::()); rsx! { div { diff --git a/examples/global.rs b/examples/global.rs index 5030bd30d..f3659845c 100644 --- a/examples/global.rs +++ b/examples/global.rs @@ -4,13 +4,13 @@ use dioxus::prelude::*; -static COUNT: GlobalSignal = Signal::global(|| 0); -static DOUBLED_COUNT: GlobalSelector = Signal::global_selector(|| COUNT() * 2); - fn main() { launch(app); } +static COUNT: GlobalSignal = Signal::global(|| 0); +static DOUBLED_COUNT: GlobalMemo = Signal::global_memo(|| COUNT() * 2); + fn app() -> Element { rsx! { h1 { "{COUNT} x 2 = {DOUBLED_COUNT}" } diff --git a/examples/svg.rs b/examples/svg.rs index 1ba7c4e32..a96511230 100644 --- a/examples/svg.rs +++ b/examples/svg.rs @@ -29,7 +29,7 @@ fn Dice() -> Element { ]; let mut value = use_signal(|| 5); - let active_dots = use_selector(move || &DOTS_FOR_VALUE[(value() - 1) as usize]); + let active_dots = use_memo(move || &DOTS_FOR_VALUE[(value() - 1) as usize]); rsx! { svg { diff --git a/examples/todomvc.rs b/examples/todomvc.rs index c3187c3f6..67d3662a9 100644 --- a/examples/todomvc.rs +++ b/examples/todomvc.rs @@ -28,9 +28,9 @@ fn app() -> Element { let mut filter = use_signal(|| FilterState::All); let active_todo_count = - use_selector(move || todos.read().values().filter(|item| !item.checked).count()); + use_memo(move || todos.read().values().filter(|item| !item.checked).count()); - let filtered_todos = use_selector(move || { + let filtered_todos = use_memo(move || { let mut filtered_todos = todos .read() .iter() @@ -120,8 +120,8 @@ fn TodoHeader(mut todos: Signal>) -> Element { #[component] fn TodoEntry(mut todos: Signal>, id: u32) -> Element { let mut is_editing = use_signal(|| false); - let checked = use_selector(move || todos.read().get(&id).unwrap().checked); - let contents = use_selector(move || todos.read().get(&id).unwrap().contents.clone()); + let checked = use_memo(move || todos.read().get(&id).unwrap().checked); + let contents = use_memo(move || todos.read().get(&id).unwrap().contents.clone()); rsx! { li { class: if checked() { "completed" }, class: if is_editing() { "editing" }, @@ -170,7 +170,7 @@ fn ListFooter( active_todo_count: ReadOnlySignal, mut filter: Signal, ) -> Element { - let show_clear_completed = use_selector(move || todos.read().values().any(|todo| todo.checked)); + let show_clear_completed = use_memo(move || todos.read().values().any(|todo| todo.checked)); rsx! { footer { class: "footer", diff --git a/packages/hooks/src/lib.rs b/packages/hooks/src/lib.rs index 4f5a8c35b..b36bf4ec5 100644 --- a/packages/hooks/src/lib.rs +++ b/packages/hooks/src/lib.rs @@ -67,6 +67,9 @@ pub use use_coroutine::*; mod use_future; pub use use_future::*; +mod use_sorted; +pub use use_sorted::*; + // mod use_on_create; // pub use use_on_create::*; diff --git a/packages/hooks/src/use_sorted.rs b/packages/hooks/src/use_sorted.rs new file mode 100644 index 000000000..feb098f52 --- /dev/null +++ b/packages/hooks/src/use_sorted.rs @@ -0,0 +1,66 @@ +use std::cmp::Ordering; +use std::ops::DerefMut; + +use dioxus_signals::{use_memo, ReadOnlySignal, Signal}; + +pub fn use_sorted( + collection: impl FnMut() -> Signal, +) -> ReadOnlySignal> +// pub fn use_sorted(iterable: impl FnMut() -> Signal) -> ReadOnlySignal +// where +// S: Into>, +// T: Ord, +// I: DerefMut + Clone + PartialEq, +{ + use_memo(move || { + todo!() + // let mut iterable = collection(); + // iterable.sort(); + // iterable + }) + // let iterable = iterable.into(); + + // // use_memo(f) + + // create_memo(move |_| { + // let mut iterable = iterable.get(); + // iterable.sort(); + // iterable + // }) + // .into() +} + +// /// Version of [`use_sorted`] with a compare function. +// pub fn use_sorted_by(iterable: S, cmp_fn: F) -> Signal +// where +// S: Into>, +// I: DerefMut + Clone + PartialEq, +// F: FnMut(&T, &T) -> Ordering + Clone + 'static, +// { +// let iterable = iterable.into(); + +// create_memo(move |_| { +// let mut iterable = iterable.get(); +// iterable.sort_by(cmp_fn.clone()); +// iterable +// }) +// .into() +// } + +// /// Version of [`use_sorted`] by key. +// pub fn use_sorted_by_key(iterable: S, key_fn: F) -> Signal +// where +// S: Into>, +// I: DerefMut + Clone + PartialEq, +// K: Ord, +// F: FnMut(&T) -> K + Clone + 'static, +// { +// let iterable = iterable.into(); + +// create_memo(move |_| { +// let mut iterable = iterable.get(); +// iterable.sort_by_key(key_fn.clone()); +// iterable +// }) +// .into() +// } diff --git a/packages/signals/README.md b/packages/signals/README.md index 6cbf2efc7..56dd8d47d 100644 --- a/packages/signals/README.md +++ b/packages/signals/README.md @@ -97,7 +97,7 @@ fn Child() -> Element { In addition to local subscriptions in components, `dioxus-signals` provides a way to derive data with local subscriptions. -The use_selector hook will only rerun when any signals inside the hook change: +The use_memo hook will only rerun when any signals inside the hook change: ```rust use dioxus::prelude::*; @@ -106,7 +106,7 @@ use dioxus_signals::*; #[component] fn App() -> Element { let signal = use_signal(|| 0); - let doubled = use_selector(|| signal * 2); + let doubled = use_memo(|| signal * 2); rsx! { button { diff --git a/packages/signals/examples/dependancies.rs b/packages/signals/examples/dependancies.rs index 84d70f743..c53022e95 100644 --- a/packages/signals/examples/dependancies.rs +++ b/packages/signals/examples/dependancies.rs @@ -16,7 +16,7 @@ fn app() -> Element { let mut local_state = use_signal(|| 0); - let computed = use_selector_with_dependencies((&local_state(),), move |(local_state,)| { + let computed = use_memo_with_dependencies((&local_state(),), move |(local_state,)| { local_state * 2 + signal.cloned() }); diff --git a/packages/signals/examples/selector.rs b/packages/signals/examples/selector.rs index c1ca1682a..98c989e05 100644 --- a/packages/signals/examples/selector.rs +++ b/packages/signals/examples/selector.rs @@ -8,7 +8,7 @@ fn main() { #[component] fn App() -> Element { let mut signal = use_signal(|| 0); - let doubled = use_selector(move || signal * 2); + let doubled = use_memo(move || signal * 2); rsx! { button { diff --git a/packages/signals/src/comparer.rs b/packages/signals/src/comparer.rs index f13204c1e..1c9de1cbc 100644 --- a/packages/signals/src/comparer.rs +++ b/packages/signals/src/comparer.rs @@ -15,7 +15,7 @@ pub struct Comparer> = UnsyncStorage> { impl Comparer { /// Creates a new Comparer which efficiently tracks when a value changes to check if it is equal to a set of values. /// - /// Generally, you shouldn't need to use this hook. Instead you can use [`crate::use_selector`]. If you have many values that you need to compare to a single value, this hook will change updates from O(n) to O(1) where n is the number of values you are comparing to. + /// Generally, you shouldn't need to use this hook. Instead you can use [`crate::use_memo`]. If you have many values that you need to compare to a single value, this hook will change updates from O(n) to O(1) where n is the number of values you are comparing to. pub fn new(mut f: impl FnMut() -> R + 'static) -> Comparer { let subscribers: CopyValue>> = CopyValue::new(FxHashMap::default()); @@ -47,7 +47,7 @@ impl Comparer { impl>> Comparer { /// Creates a new Comparer that may be `Sync + Send` which efficiently tracks when a value changes to check if it is equal to a set of values. /// - /// Generally, you shouldn't need to use this hook. Instead you can use [`crate::use_selector`]. If you have many values that you need to compare to a single value, this hook will change updates from O(n) to O(1) where n is the number of values you are comparing to. + /// Generally, you shouldn't need to use this hook. Instead you can use [`crate::use_memo`]. If you have many values that you need to compare to a single value, this hook will change updates from O(n) to O(1) where n is the number of values you are comparing to. pub fn new_maybe_sync(mut f: impl FnMut() -> R + 'static) -> Comparer { let subscribers: CopyValue>> = CopyValue::new(FxHashMap::default()); @@ -102,7 +102,7 @@ impl>> Copy for Comparer {} /// Creates a new Comparer which efficiently tracks when a value changes to check if it is equal to a set of values. /// -/// Generally, you shouldn't need to use this hook. Instead you can use [`crate::use_selector`]. If you have many values that you need to compare to a single value, this hook will change updates from O(n) to O(1) where n is the number of values you are comparing to. +/// Generally, you shouldn't need to use this hook. Instead you can use [`crate::use_memo`]. If you have many values that you need to compare to a single value, this hook will change updates from O(n) to O(1) where n is the number of values you are comparing to. /// /// ```rust /// use dioxus::prelude::*; diff --git a/packages/signals/src/global.rs b/packages/signals/src/global.rs index 9817a6c07..849c446e3 100644 --- a/packages/signals/src/global.rs +++ b/packages/signals/src/global.rs @@ -201,17 +201,17 @@ impl Deref for GlobalSignal { } /// A signal that can be accessed from anywhere in the application and created in a static -pub struct GlobalSelector { +pub struct GlobalMemo { selector: fn() -> T, } -impl GlobalSelector { +impl GlobalMemo { /// Create a new global signal - pub const fn new(selector: fn() -> T) -> GlobalSelector + pub const fn new(selector: fn() -> T) -> GlobalMemo where T: PartialEq, { - GlobalSelector { selector } + GlobalMemo { selector } } /// Get the signal that backs this global. @@ -266,7 +266,7 @@ impl GlobalSelector { } } -impl IntoAttributeValue for GlobalSelector +impl IntoAttributeValue for GlobalMemo where T: Clone + IntoAttributeValue, { @@ -275,7 +275,7 @@ where } } -impl GlobalSelector { +impl GlobalMemo { /// Get the current value of the signal. This will subscribe the current scope to the signal. /// If the signal has been dropped, this will panic. #[track_caller] @@ -284,7 +284,7 @@ impl GlobalSelector { } } -impl PartialEq for GlobalSelector { +impl PartialEq for GlobalMemo { fn eq(&self, other: &Self) -> bool { std::ptr::eq(self, other) } @@ -293,7 +293,7 @@ impl PartialEq for GlobalSelector { /// Allow calling a signal with signal() syntax /// /// Currently only limited to copy types, though could probably specialize for string/arc/rc -impl Deref for GlobalSelector { +impl Deref for GlobalMemo { type Target = dyn Fn() -> T; fn deref(&self) -> &Self::Target { diff --git a/packages/signals/src/impls.rs b/packages/signals/src/impls.rs index f21bccf25..fc5df7169 100644 --- a/packages/signals/src/impls.rs +++ b/packages/signals/src/impls.rs @@ -1,6 +1,6 @@ use crate::rt::CopyValue; use crate::signal::{ReadOnlySignal, Signal, Write}; -use crate::{GlobalSelector, GlobalSignal, SignalData}; +use crate::{GlobalMemo, GlobalSignal, SignalData}; use generational_box::{GenerationalRef, Mappable}; use generational_box::{MappableMut, Storage}; @@ -414,16 +414,16 @@ impl GlobalSignal> { } } -read_impls!(GlobalSelector: PartialEq); +read_impls!(GlobalMemo: PartialEq); -impl GlobalSelector> { +impl GlobalMemo> { /// Read a value from the inner vector. pub fn get(&'static self, index: usize) -> Option>> { GenerationalRef::, Ref<'static, Vec>>::try_map(self.read(), move |v| v.get(index)) } } -impl GlobalSelector> { +impl GlobalMemo> { /// Unwraps the inner value and clones it. pub fn unwrap(&'static self) -> T where diff --git a/packages/signals/src/selector.rs b/packages/signals/src/selector.rs index d8f38e10a..ab888183a 100644 --- a/packages/signals/src/selector.rs +++ b/packages/signals/src/selector.rs @@ -15,7 +15,7 @@ use crate::{signal::SignalData, ReadOnlySignal, Signal}; /// /// fn App() -> Element { /// let mut count = use_signal(|| 0); -/// let double = use_selector(move || count * 2); +/// let double = use_memo(move || count * 2); /// count += 1; /// assert_eq!(double.value(), count * 2); /// @@ -24,8 +24,8 @@ use crate::{signal::SignalData, ReadOnlySignal, Signal}; /// ``` #[track_caller] #[must_use = "Consider using `use_effect` to rerun a callback when dependencies change"] -pub fn use_selector(f: impl FnMut() -> R + 'static) -> ReadOnlySignal { - use_maybe_sync_selector(f) +pub fn use_memo(f: impl FnMut() -> R + 'static) -> ReadOnlySignal { + use_maybe_sync_memo(f) } /// Creates a new Selector that may be sync. The selector will be run immediately and whenever any signal it reads changes. @@ -38,19 +38,19 @@ pub fn use_selector(f: impl FnMut() -> R + 'static) -> ReadOnlySig /// /// fn App(cx: Scope) -> Element { /// let mut count = use_signal(cx, || 0); -/// let double = use_selector(cx, move || count * 2); +/// let double = use_memo(cx, move || count * 2); /// count += 1; /// assert_eq!(double.value(), count * 2); -/// +/// /// render! { "{double}" } /// } /// ``` #[track_caller] #[must_use = "Consider using `use_effect` to rerun a callback when dependencies change"] -pub fn use_maybe_sync_selector>>( +pub fn use_maybe_sync_memo>>( f: impl FnMut() -> R + 'static, ) -> ReadOnlySignal { - use_hook(|| Signal::maybe_sync_selector(f)) + use_hook(|| Signal::maybe_sync_memo(f)) } /// Creates a new unsync Selector with some local dependencies. The selector will be run immediately and whenever any signal it reads or any dependencies it tracks changes @@ -63,15 +63,15 @@ pub fn use_maybe_sync_selector>>( /// /// fn App(cx: Scope) -> Element { /// let mut local_state = use_state(cx, || 0); -/// let double = use_selector_with_dependencies(cx, (local_state.get(),), move |(local_state,)| local_state * 2); +/// let double = use_memo_with_dependencies(cx, (local_state.get(),), move |(local_state,)| local_state * 2); /// local_state.set(1); -/// +/// /// render! { "{double}" } /// } /// ``` #[track_caller] #[must_use = "Consider using `use_effect` to rerun a callback when dependencies change"] -pub fn use_selector_with_dependencies( +pub fn use_memo_with_dependencies( dependencies: D, f: impl FnMut(D::Out) -> R + 'static, ) -> ReadOnlySignal @@ -91,9 +91,9 @@ where /// /// fn App(cx: Scope) -> Element { /// let mut local_state = use_state(cx, || 0); -/// let double = use_selector_with_dependencies(cx, (local_state.get(),), move |(local_state,)| local_state * 2); +/// let double = use_memo_with_dependencies(cx, (local_state.get(),), move |(local_state,)| local_state * 2); /// local_state.set(1); -/// +/// /// render! { "{double}" } /// } /// ``` @@ -112,7 +112,7 @@ where { let mut dependencies_signal = use_signal(|| dependencies.out()); let selector = use_hook(|| { - Signal::maybe_sync_selector(move || { + Signal::maybe_sync_memo(move || { let deref = &*dependencies_signal.read(); f(deref.clone()) }) diff --git a/packages/signals/src/signal.rs b/packages/signals/src/signal.rs index 21e14bb9d..001ade6f7 100644 --- a/packages/signals/src/signal.rs +++ b/packages/signals/src/signal.rs @@ -1,4 +1,4 @@ -use crate::{Effect, EffectInner, GlobalSelector, GlobalSignal, MappedSignal}; +use crate::{Effect, EffectInner, GlobalMemo, GlobalSignal, MappedSignal}; use std::{ cell::RefCell, marker::PhantomData, @@ -232,11 +232,11 @@ impl Signal { impl Signal { /// Creates a new global Signal that can be used in a global static. - pub const fn global_selector(constructor: fn() -> T) -> GlobalSelector + pub const fn global_memo(constructor: fn() -> T) -> GlobalMemo where T: PartialEq, { - GlobalSelector::new(constructor) + GlobalMemo::new(constructor) } /// Creates a new unsync Selector. The selector will be run immediately and whenever any signal it reads changes. @@ -244,14 +244,14 @@ impl Signal { /// Selectors can be used to efficiently compute derived data from signals. #[track_caller] pub fn selector(f: impl FnMut() -> T + 'static) -> ReadOnlySignal { - Self::maybe_sync_selector(f) + Self::maybe_sync_memo(f) } /// Creates a new Selector that may be Sync + Send. The selector will be run immediately and whenever any signal it reads changes. /// /// Selectors can be used to efficiently compute derived data from signals. #[track_caller] - pub fn maybe_sync_selector>>( + pub fn maybe_sync_memo>>( mut f: impl FnMut() -> T + 'static, ) -> ReadOnlySignal { let mut state = Signal:: {