todomvc.rs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. use dioxus_core::prelude::*;
  2. use dioxus_web::WebsysRenderer;
  3. use recoil::{use_recoil_callback, RecoilContext};
  4. use uuid::Uuid;
  5. static TODOS: AtomFamily<Uuid, TodoItem> = atom_family(|_| {});
  6. fn main() {
  7. wasm_bindgen_futures::spawn_local(WebsysRenderer::start(|ctx, props| {
  8. let global_reducer = use_recoil_callback(|| ());
  9. let todos = use_atom(TODOS).iter().map(|(order, item)| {
  10. rsx!(TodoItem {
  11. key: "{order}",
  12. id: item.id,
  13. })
  14. });
  15. ctx.render(rsx! {
  16. div {
  17. {todos}
  18. Footer {}
  19. }
  20. })
  21. }))
  22. }
  23. #[derive(Debug, PartialEq, Clone)]
  24. pub struct TodoItem {
  25. pub id: Uuid,
  26. pub checked: bool,
  27. pub contents: String,
  28. }
  29. // build a global context for the app
  30. // as we scale the app, we can create separate, stateful impls
  31. impl RecoilContext<()> {
  32. fn add_todo(&self) {}
  33. fn remove_todo(&self) {}
  34. fn select_all_todos(&self) {}
  35. }
  36. mod hooks {
  37. use super::*;
  38. fn use_keyboard_shortcuts(ctx: &Context) {}
  39. }
  40. // The data model that the todo mvc uses
  41. mod model {
  42. use std::{borrow::BorrowMut, future::Future};
  43. use super::*;
  44. #[derive(Debug, PartialEq, Clone)]
  45. pub struct TodoItem {
  46. pub id: Uuid,
  47. pub checked: bool,
  48. pub contents: String,
  49. }
  50. fn atom() {}
  51. // struct Dispatcher {}
  52. struct AppContext<T: Clone> {
  53. _t: std::rc::Rc<T>,
  54. }
  55. // pub fn use_appcontext<T: Clone>(ctx: &Context, f: impl FnOnce() -> T) -> AppContext<T> {
  56. // todo!()
  57. // }
  58. // static TodoList: ContextFamily = context_family();
  59. // struct TodoBoss<'a> {}
  60. // fn use_recoil_todos() -> TodoBoss {}
  61. // pub fn use_context_family(ctx: &Context) {}
  62. impl<T: Clone> AppContext<T> {
  63. fn dispatch(&self, f: impl FnOnce(&mut T)) {}
  64. fn async_dispatch(&self, f: impl Future<Output = ()>) {}
  65. fn get<G>(&self, f: impl Fn(&T) -> &G) -> &G {
  66. f(&self._t)
  67. }
  68. fn set(&self, orig: &mut std::borrow::Cow<T>) {
  69. let r = orig.to_mut();
  70. }
  71. }
  72. // // use im-rc if your contexts are too large to clone!
  73. // // or, dangerously mutate and update subscriptions manually
  74. // #[derive(Clone, Debug, PartialEq)]
  75. // pub struct TodoManager {
  76. // items: Vec<u32>,
  77. // }
  78. // // App context is an ergonomic way of sharing data models through a tall tree
  79. // // Because it holds onto the source data with Rc, it's cheap to clone through props and allows advanced memoization
  80. // // It's particularly useful when moving through tall trees, or iterating through complex data models.
  81. // // By wrapping the source type, we can forward any mutation through "dispatch", making it clear when clones occur.
  82. // // This also enables traditional method-style
  83. // impl AppContext<TodoManager> {
  84. // fn get_todos(&self, ctx: &Context) {}
  85. // fn remove_todo(&self, id: Uuid) {
  86. // self.dispatch(|f| {
  87. // // todos... remove
  88. // })
  89. // }
  90. // async fn push_todo(&self, todo: TodoItem) {
  91. // self.dispatch(|f| {
  92. // //
  93. // f.items.push(10);
  94. // });
  95. // }
  96. // fn add_todo(&self) {
  97. // // self.dispatch(|f| {});
  98. // // let items = self.get(|f| &f.items);
  99. // }
  100. // }
  101. // pub enum TodoActions {}
  102. // impl TodoManager {
  103. // pub fn reduce(s: &mut Rc<Self>, action: TodoActions) {
  104. // match action {
  105. // _ => {}
  106. // }
  107. // }
  108. // pub fn new() -> Rc<Self> {
  109. // todo!()
  110. // }
  111. // pub fn get_todo(&self, id: Uuid) -> &TodoItem {
  112. // todo!()
  113. // }
  114. // pub fn get_todos(&self) -> &BTreeMap<String, TodoItem> {
  115. // todo!()
  116. // }
  117. // }
  118. // pub struct TodoHandle {}
  119. // impl TodoHandle {
  120. // fn get_todo(&self, id: Uuid) -> &TodoItem {
  121. // todo!()
  122. // }
  123. // fn add_todo(&self, todo: TodoItem) {}
  124. // }
  125. // // use_reducer, but exposes the reducer and context to children
  126. // fn use_reducer_context() {}
  127. // fn use_context_selector() {}
  128. // fn use_context<'b, 'c, Root: 'static, Item: 'c>(
  129. // ctx: &'b Context<'c>,
  130. // f: impl Fn(Root) -> &'c Item,
  131. // ) -> &'c Item {
  132. // todo!()
  133. // }
  134. // pub fn use_todo_item<'b, 'c>(ctx: &'b Context<'c>, item: Uuid) -> &'c TodoItem {
  135. // todo!()
  136. // // ctx.use_hook(|| TodoManager::new(), |hook| {}, cleanup)
  137. // }
  138. // fn use_todos(ctx: &Context) -> TodoHandle {
  139. // todo!()
  140. // }
  141. // fn use_todo_context(ctx: &Context) -> AppContext<TodoManager> {
  142. // todo!()
  143. // }
  144. // fn test(ctx: Context) {
  145. // let todos = use_todos(&ctx);
  146. // let todo = todos.get_todo(Uuid::new_v4());
  147. // let c = use_todo_context(&ctx);
  148. // // todos.add_todo();
  149. // }
  150. }
  151. mod recoil {
  152. pub struct RecoilContext<T: 'static> {
  153. _inner: T,
  154. }
  155. impl<T: 'static> RecoilContext<T> {
  156. /// Get the value of an atom. Returns a reference to the underlying data.
  157. pub fn get(&self) {}
  158. /// Replace an existing value with a new value
  159. ///
  160. /// This does not replace the value instantly, and all calls to "get" within the current scope will return
  161. pub fn set(&self) {}
  162. // Modify lets you modify the value in place. However, because there's no previous value around to compare
  163. // the new one with, we are unable to memoize the change. As such, all downsteam users of this Atom will
  164. // be updated, causing all subsrcibed components to re-render.
  165. //
  166. // This is fine for most values, but might not be performant when dealing with collections. For collections,
  167. // use the "Family" variants as these will stay memoized for inserts, removals, and modifications.
  168. //
  169. // Note - like "set" this won't propogate instantly. Once all "gets" are dropped, only then will we run the
  170. pub fn modify(&self) {}
  171. }
  172. pub fn use_recoil_callback<G>(f: impl Fn() -> G) -> RecoilContext<G> {
  173. todo!()
  174. }
  175. }