From c7469a6d450fbaed051f78fbd1a9733f8f4e106d Mon Sep 17 00:00:00 2001 From: marc2332 Date: Sat, 21 Sep 2024 13:52:40 +0200 Subject: [PATCH] more --- book/src/SUMMARY.md | 2 + book/src/learn/accessibility.md | 2 +- book/src/learn/lifecycle.md | 3 +- book/src/learn/performance.md | 83 +++++++++++++++++++ book/src/learn/state_management.md | 4 +- .../src/learn/state_management/memoization.md | 23 +++++ 6 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 book/src/learn/performance.md create mode 100644 book/src/learn/state_management/memoization.md diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 56648cab1..f7896d080 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -17,6 +17,7 @@ - [Global Signals](./learn/state_management/global_signals.md) - [Lifecycle](./learn/lifecycle.md) - [Context](./learn/state_management/context.md) + - [Memoization](./learn/state_management/memoization.md) - [Third Party](./learn/state_management/third_party.md) - [Async](./learn/async.md) - [Themes](./learn/themes.md) @@ -30,6 +31,7 @@ - [Built-in Hooks](./learn/built_in_hooks.md) - [Devtools](./learn/devtools.md) - [Publishing](./learn/publishing.md) +- [Performance](./learn/performance.md) # Other - [FAQ](./faq.md) diff --git a/book/src/learn/accessibility.md b/book/src/learn/accessibility.md index dc1a503be..173341a91 100644 --- a/book/src/learn/accessibility.md +++ b/book/src/learn/accessibility.md @@ -12,7 +12,7 @@ fn app() -> Element { rect { width: "100%", height: "100%", - focus_id: my_focus.attribute(), + a11y_id: my_focus.attribute(), onclick: move |_| my_focus.focus(), label { "{my_focus.is_focused()}" diff --git a/book/src/learn/lifecycle.md b/book/src/learn/lifecycle.md index 6b8c06d37..f2c4f12ca 100644 --- a/book/src/learn/lifecycle.md +++ b/book/src/learn/lifecycle.md @@ -40,7 +40,8 @@ fn app() -> Element { let mut signal = use_signal(|| 1); use_effect(move || { - // Because we are reading this signal now the effect is subscribed to any change + // Because we are reading this signal + // now the effect is subscribed to any change let value = signal(); println!("Value of signal is {value}"); }); diff --git a/book/src/learn/performance.md b/book/src/learn/performance.md new file mode 100644 index 000000000..70c0a58c3 --- /dev/null +++ b/book/src/learn/performance.md @@ -0,0 +1,83 @@ +# Performance + +Collection of things to avoid and improve to have a better performance. + +### 1. Using use_effect to synchronize state +The `use_effect` hook is sometimes missused as a synchronization between states + +```rs +fn app() -> Element { + let mut state = use_signal(|| 1); + let mut double_state = use_signal(|| 1); + + use_effect(move || { + // Update double_state whenever `state` changes + double_state.set(state() * 2) + }); + + rsx!( + label { + onclick: move |_| state += 1, + "{state} * 2 = {double_state}" + } + ) +} +``` + +This is bad because we are storing a derived value (double_state) in a reactive wrapper (signala). +The flow would have been: +``` + (initial) -> state: 0 , double_state: 0 + (state gets updated) -> state: 1 , double_state: 0 +(effect runs and updates double_state) -> state: 1 , double_state: 1 +``` + + +#### Manual signal derivation + +We can simply create a temporary variable in which to store the derived value from the signal. +Because we are reading `double_state`, whenever `state` changes this component function will reerun, so `double_state` will always be up to date. + +```rs +fn app() -> Element { + let mut state = use_signal(|| 1); + let double_state = state() * 2; + + rsx!( + label { + onclick: move |_| state += 1, + "{state} * 2 = {double_state}" + } + ) +} +``` + +Now, the flow would be: +``` + (initial) -> state: 0 , double_state: 0 +(state gets updated and double_state derived) -> state: 1 , double_state: 1 +``` + +### Reactive signal derivation + +We can also use `use_memo` to memoize derived values. This is very useful for values that are expensive to compute (which isn't the case with simple numeric operation) + +```rs +fn app() -> Element { + let mut state = use_signal(|| 1); + let double_state = use_memo(move || state() * 2); + + rsx!( + label { + onclick: move |_| state += 1, + "{state} * 2 = {double_state}" + } + ) +} +``` + +The flow would be: +``` + (initial) -> state: 0 , double_state: 0 +(state gets updated and double_state memo run synchronously) -> state: 1 , double_state: 1 +``` \ No newline at end of file diff --git a/book/src/learn/state_management.md b/book/src/learn/state_management.md index 3cbf77963..cd271e2ce 100644 --- a/book/src/learn/state_management.md +++ b/book/src/learn/state_management.md @@ -2,9 +2,11 @@ Dioxus and Freya apps, have multiple ways of state management. -See the different options: +See the different features: - [Signals](./state_management/signals.md) - [Global Signals](./state_management/globla_signals.md) +- [Lifecycle](./state_management/lifecycle.md) - [Context](./state_management/context.md) +- [Memoization](./state_management/memoization.md) - [Third Party](./state_management/third_party.md) \ No newline at end of file diff --git a/book/src/learn/state_management/memoization.md b/book/src/learn/state_management/memoization.md new file mode 100644 index 000000000..4161d1b99 --- /dev/null +++ b/book/src/learn/state_management/memoization.md @@ -0,0 +1,23 @@ +# Memoization + +You can memoize values by using the `use_memo` hook. This can be useful to have reactive derived across components or to cache expensive value to compute. + +```rs +fn app() -> Element { + let mut state = use_signal(|| 1); + // `use_memo` returns a `ReadOnlySignal`, as the name says it is a Signal + // that you can read and subscribe to but you cannot mutate + // as its value can only be changed when the memo runs + let double_state = use_memo(move || { + // Just like `use_effect`, whenever a signal that is read in here is changed, the memo will rerun. + state() * 2 + }); + + rsx!( + label { + onclick: move |_| state += 1, + "{double_state}" + } + ) +} +``` \ No newline at end of file