1
0

use_signal.rs 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. use dioxus_core::prelude::*;
  2. use dioxus_signals::{Signal, SignalData, Storage, SyncStorage, UnsyncStorage};
  3. /// Creates a new Signal. Signals are a Copy state management solution with automatic dependency tracking.
  4. ///
  5. /// ```rust
  6. /// use dioxus::prelude::*;
  7. /// use dioxus_signals::*;
  8. ///
  9. /// fn App() -> Element {
  10. /// let mut count = use_signal(|| 0);
  11. ///
  12. /// // Because signals have automatic dependency tracking, if you never read them in a component, that component will not be re-rended when the signal is updated.
  13. /// // The app component will never be rerendered in this example.
  14. /// rsx! { Child { state: count } }
  15. /// }
  16. ///
  17. /// #[component]
  18. /// fn Child(state: Signal<u32>) -> Element {
  19. /// use_future(move || async move {
  20. /// // Because the signal is a Copy type, we can use it in an async block without cloning it.
  21. /// *state.write() += 1;
  22. /// });
  23. ///
  24. /// rsx! {
  25. /// button {
  26. /// onclick: move |_| *state.write() += 1,
  27. /// "{state}"
  28. /// }
  29. /// }
  30. /// }
  31. /// ```
  32. ///
  33. #[doc = include_str!("../docs/rules_of_hooks.md")]
  34. #[doc = include_str!("../docs/moving_state_around.md")]
  35. #[doc(alias = "use_state")]
  36. #[track_caller]
  37. #[must_use]
  38. pub fn use_signal<T: 'static>(f: impl FnOnce() -> T) -> Signal<T, UnsyncStorage> {
  39. use_maybe_signal_sync(f)
  40. }
  41. /// Creates a new `Send + Sync`` Signal. Signals are a Copy state management solution with automatic dependency tracking.
  42. ///
  43. /// ```rust
  44. /// use dioxus::prelude::*;
  45. /// use dioxus_signals::*;
  46. ///
  47. /// fn App() -> Element {
  48. /// let mut count = use_signal_sync(|| 0);
  49. ///
  50. /// // Because signals have automatic dependency tracking, if you never read them in a component, that component will not be re-rended when the signal is updated.
  51. /// // The app component will never be rerendered in this example.
  52. /// rsx! { Child { state: count } }
  53. /// }
  54. ///
  55. /// #[component]
  56. /// fn Child(state: Signal<u32, SyncStorage>) -> Element {
  57. /// use_future(move || async move {
  58. /// // This signal is Send + Sync, so we can use it in an another thread
  59. /// tokio::spawn(async move {
  60. /// // Because the signal is a Copy type, we can use it in an async block without cloning it.
  61. /// *state.write() += 1;
  62. /// }).await;
  63. /// });
  64. ///
  65. /// rsx! {
  66. /// button {
  67. /// onclick: move |_| *state.write() += 1,
  68. /// "{state}"
  69. /// }
  70. /// }
  71. /// }
  72. /// ```
  73. #[doc(alias = "use_rw")]
  74. #[must_use]
  75. #[track_caller]
  76. pub fn use_signal_sync<T: Send + Sync + 'static>(f: impl FnOnce() -> T) -> Signal<T, SyncStorage> {
  77. use_maybe_signal_sync(f)
  78. }
  79. #[must_use]
  80. #[track_caller]
  81. fn use_maybe_signal_sync<T: 'static, U: Storage<SignalData<T>>>(
  82. f: impl FnOnce() -> T,
  83. ) -> Signal<T, U> {
  84. let caller = std::panic::Location::caller();
  85. // todo: (jon)
  86. // By default, we want to unsubscribe the current component from the signal on every render
  87. // any calls to .read() in the body will re-subscribe the component to the signal
  88. // use_before_render(move || signal.unsubscribe(current_scope_id().unwrap()));
  89. use_hook(|| Signal::new_with_caller(f(), caller))
  90. }