hooks.rs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. use std::rc::Rc;
  2. use dioxus_core::{hooks::use_ref, prelude::Context};
  3. use crate::{Atom, AtomValue, Readable, RecoilApi, RecoilRoot};
  4. /// This hook initializes the Recoil Context - should only be placed once per app.
  5. ///
  6. ///
  7. /// ```ignore
  8. ///
  9. ///
  10. ///
  11. /// ```
  12. pub fn init_root(ctx: Context) {
  13. ctx.use_create_context(move || RecoilRoot::new())
  14. }
  15. /// Use an atom and its setter
  16. ///
  17. /// This hook subscribes the component to any updates to the atom.
  18. ///
  19. /// ```rust
  20. /// const TITLE: Atom<&str> = atom(|_| "default");
  21. ///
  22. /// static App: FC<()> = |ctx, props| {
  23. /// let (title, set_title) = recoil::use_state(ctx, &TITLE);
  24. /// ctx.render(rsx!{
  25. /// div {
  26. /// "{title}"
  27. /// button {"on", onclick: move |_| set_title("on")}
  28. /// button {"off", onclick: move |_| set_title("off")}
  29. /// }
  30. /// })
  31. /// }
  32. ///
  33. /// ```
  34. pub fn use_recoil_state<'a, T: PartialEq + 'static>(
  35. ctx: Context<'a>,
  36. readable: &'static impl Readable<T>,
  37. ) -> (&'a T, &'a Rc<dyn Fn(T)>) {
  38. struct RecoilStateInner<G: AtomValue> {
  39. root: Rc<RecoilRoot>,
  40. value: Rc<G>,
  41. setter: Rc<dyn Fn(G)>,
  42. }
  43. let root = ctx.use_context::<RecoilRoot>();
  44. let (subscriber_id, value) = root.subscribe_consumer(readable, ctx.schedule_update());
  45. ctx.use_hook(
  46. move || RecoilStateInner {
  47. value,
  48. root: root.clone(),
  49. setter: Rc::new(move |new_val| root.update_atom(readable, new_val)),
  50. },
  51. move |hook| {
  52. hook.value = hook.root.load_value(readable);
  53. (hook.value.as_ref(), &hook.setter)
  54. },
  55. // Make sure we unsubscribe
  56. // It's not *wrong* for a dead component to receive updates, but it is less performant
  57. move |hook| hook.root.drop_consumer(subscriber_id),
  58. )
  59. }
  60. ///
  61. ///
  62. ///
  63. /// ```ignore
  64. /// let (title, set_title) = recoil::use_state()
  65. ///
  66. ///
  67. ///
  68. /// ```
  69. pub fn use_recoil_value<'a, T: PartialEq>(ctx: Context<'a>, t: &'static impl Readable<T>) -> &'a T {
  70. todo!()
  71. }
  72. /// Update an atom's value without
  73. ///
  74. /// Enable the ability to set a value without subscribing the componet
  75. ///
  76. ///
  77. ///
  78. /// ```ignore
  79. /// let (title, set_title) = recoil::use_state()
  80. ///
  81. ///
  82. ///
  83. /// ```
  84. pub fn use_set_state<'a, T: PartialEq>(c: Context<'a>, t: &'static Atom<T>) -> &'a Rc<dyn Fn(T)> {
  85. todo!()
  86. }
  87. ///
  88. ///
  89. ///
  90. /// ```ignore
  91. /// let (title, set_title) = recoil::use_state()
  92. ///
  93. ///
  94. ///
  95. /// ```
  96. pub fn use_recoil_callback<'a, F: 'a>(
  97. ctx: Context<'a>,
  98. f: impl Fn(RecoilApi) -> F + 'static,
  99. ) -> &F {
  100. todo!()
  101. }