浏览代码

rename use_selector to use_memo

Jonathan Kelley 1 年之前
父节点
当前提交
06d9b575b7

+ 1 - 1
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<Rc<dyn Debug>>);
+    let mut events = use_signal(|| VecDeque::new() as VecDeque<Rc<dyn Debug>>);
 
     let mut log_event = move |event: Rc<dyn Debug>| {
         let mut events = events.write();

+ 13 - 32
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",

+ 1 - 1
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::<i32>());
+    let sum = use_memo(move || counters.read().iter().copied().sum::<i32>());
 
     rsx! {
         div {

+ 3 - 3
examples/global.rs

@@ -4,13 +4,13 @@
 
 use dioxus::prelude::*;
 
-static COUNT: GlobalSignal<i32> = Signal::global(|| 0);
-static DOUBLED_COUNT: GlobalSelector<i32> = Signal::global_selector(|| COUNT() * 2);
-
 fn main() {
     launch(app);
 }
 
+static COUNT: GlobalSignal<i32> = Signal::global(|| 0);
+static DOUBLED_COUNT: GlobalMemo<i32> = Signal::global_memo(|| COUNT() * 2);
+
 fn app() -> Element {
     rsx! {
         h1 { "{COUNT} x 2 = {DOUBLED_COUNT}" }

+ 1 - 1
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 {

+ 5 - 5
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<HashMap<u32, TodoItem>>) -> Element {
 #[component]
 fn TodoEntry(mut todos: Signal<HashMap<u32, TodoItem>>, 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<usize>,
     mut filter: Signal<FilterState>,
 ) -> 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",

+ 3 - 0
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::*;
 

+ 66 - 0
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<V: 'static, T: PartialEq>(
+    collection: impl FnMut() -> Signal<V>,
+) -> ReadOnlySignal<Vec<T>>
+// pub fn use_sorted<S, I, T>(iterable: impl FnMut() -> Signal<V>) -> ReadOnlySignal<T>
+// where
+//     S: Into<MaybeSignal<I>>,
+//     T: Ord,
+//     I: DerefMut<Target = [T]> + 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<S, I, T, F>(iterable: S, cmp_fn: F) -> Signal<I>
+// where
+//     S: Into<MaybeSignal<I>>,
+//     I: DerefMut<Target = [T]> + 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<S, I, T, K, F>(iterable: S, key_fn: F) -> Signal<I>
+// where
+//     S: Into<MaybeSignal<I>>,
+//     I: DerefMut<Target = [T]> + 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()
+// }

+ 2 - 2
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 {

+ 1 - 1
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()
     });
 

+ 1 - 1
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 {

+ 3 - 3
packages/signals/src/comparer.rs

@@ -15,7 +15,7 @@ pub struct Comparer<R: 'static, S: Storage<SignalData<bool>> = UnsyncStorage> {
 impl<R: Eq + Hash> Comparer<R> {
     /// 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<R> {
         let subscribers: CopyValue<FxHashMap<R, Signal<bool>>> =
             CopyValue::new(FxHashMap::default());
@@ -47,7 +47,7 @@ impl<R: Eq + Hash> Comparer<R> {
 impl<R: Eq + Hash, S: Storage<SignalData<bool>>> Comparer<R, S> {
     /// 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<R> {
         let subscribers: CopyValue<FxHashMap<R, Signal<bool>>> =
             CopyValue::new(FxHashMap::default());
@@ -102,7 +102,7 @@ impl<R, S: Storage<SignalData<bool>>> Copy for Comparer<R, S> {}
 
 /// 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::*;

+ 8 - 8
packages/signals/src/global.rs

@@ -201,17 +201,17 @@ impl<T: Clone + 'static> Deref for GlobalSignal<T> {
 }
 
 /// A signal that can be accessed from anywhere in the application and created in a static
-pub struct GlobalSelector<T: 'static> {
+pub struct GlobalMemo<T: 'static> {
     selector: fn() -> T,
 }
 
-impl<T: PartialEq + 'static> GlobalSelector<T> {
+impl<T: PartialEq + 'static> GlobalMemo<T> {
     /// Create a new global signal
-    pub const fn new(selector: fn() -> T) -> GlobalSelector<T>
+    pub const fn new(selector: fn() -> T) -> GlobalMemo<T>
     where
         T: PartialEq,
     {
-        GlobalSelector { selector }
+        GlobalMemo { selector }
     }
 
     /// Get the signal that backs this global.
@@ -266,7 +266,7 @@ impl<T: PartialEq + 'static> GlobalSelector<T> {
     }
 }
 
-impl<T: PartialEq + 'static> IntoAttributeValue for GlobalSelector<T>
+impl<T: PartialEq + 'static> IntoAttributeValue for GlobalMemo<T>
 where
     T: Clone + IntoAttributeValue,
 {
@@ -275,7 +275,7 @@ where
     }
 }
 
-impl<T: PartialEq + Clone + 'static> GlobalSelector<T> {
+impl<T: PartialEq + Clone + 'static> GlobalMemo<T> {
     /// 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<T: PartialEq + Clone + 'static> GlobalSelector<T> {
     }
 }
 
-impl<T: PartialEq + 'static> PartialEq for GlobalSelector<T> {
+impl<T: PartialEq + 'static> PartialEq for GlobalMemo<T> {
     fn eq(&self, other: &Self) -> bool {
         std::ptr::eq(self, other)
     }
@@ -293,7 +293,7 @@ impl<T: PartialEq + 'static> PartialEq for GlobalSelector<T> {
 /// Allow calling a signal with signal() syntax
 ///
 /// Currently only limited to copy types, though could probably specialize for string/arc/rc
-impl<T: PartialEq + Clone + 'static> Deref for GlobalSelector<T> {
+impl<T: PartialEq + Clone + 'static> Deref for GlobalMemo<T> {
     type Target = dyn Fn() -> T;
 
     fn deref(&self) -> &Self::Target {

+ 4 - 4
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<T: 'static> GlobalSignal<Option<T>> {
     }
 }
 
-read_impls!(GlobalSelector: PartialEq);
+read_impls!(GlobalMemo: PartialEq);
 
-impl<T: PartialEq + 'static> GlobalSelector<Vec<T>> {
+impl<T: PartialEq + 'static> GlobalMemo<Vec<T>> {
     /// Read a value from the inner vector.
     pub fn get(&'static self, index: usize) -> Option<GenerationalRef<T, Ref<'static, T>>> {
         GenerationalRef::<Vec<T>, Ref<'static, Vec<T>>>::try_map(self.read(), move |v| v.get(index))
     }
 }
 
-impl<T: PartialEq + 'static> GlobalSelector<Option<T>> {
+impl<T: PartialEq + 'static> GlobalMemo<Option<T>> {
     /// Unwraps the inner value and clones it.
     pub fn unwrap(&'static self) -> T
     where

+ 13 - 13
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<R: PartialEq>(f: impl FnMut() -> R + 'static) -> ReadOnlySignal<R> {
-    use_maybe_sync_selector(f)
+pub fn use_memo<R: PartialEq>(f: impl FnMut() -> R + 'static) -> ReadOnlySignal<R> {
+    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<R: PartialEq>(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<R: PartialEq, S: Storage<SignalData<R>>>(
+pub fn use_maybe_sync_memo<R: PartialEq, S: Storage<SignalData<R>>>(
     f: impl FnMut() -> R + 'static,
 ) -> ReadOnlySignal<R, S> {
-    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<R: PartialEq, S: Storage<SignalData<R>>>(
 ///
 /// 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<R: PartialEq, D: Dependency>(
+pub fn use_memo_with_dependencies<R: PartialEq, D: Dependency>(
     dependencies: D,
     f: impl FnMut(D::Out) -> R + 'static,
 ) -> ReadOnlySignal<R>
@@ -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())
         })

+ 5 - 5
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<T: 'static> Signal<T> {
 
 impl<T: PartialEq + 'static> Signal<T> {
     /// Creates a new global Signal that can be used in a global static.
-    pub const fn global_selector(constructor: fn() -> T) -> GlobalSelector<T>
+    pub const fn global_memo(constructor: fn() -> T) -> GlobalMemo<T>
     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<T: PartialEq + 'static> Signal<T> {
     /// Selectors can be used to efficiently compute derived data from signals.
     #[track_caller]
     pub fn selector(f: impl FnMut() -> T + 'static) -> ReadOnlySignal<T> {
-        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<S: Storage<SignalData<T>>>(
+    pub fn maybe_sync_memo<S: Storage<SignalData<T>>>(
         mut f: impl FnMut() -> T + 'static,
     ) -> ReadOnlySignal<T, S> {
         let mut state = Signal::<T, S> {