Kaynağa Gözat

wip: parity document

Jonathan Kelley 4 yıl önce
ebeveyn
işleme
ba97541

+ 13 - 2
notes/CHANGELOG.md

@@ -5,6 +5,10 @@ Welcome to the first iteration of the Dioxus Virtual DOM! This release brings su
 - Server-rendering with custom ToString implementation
 - State management
 - Build CLI
+- Foundational hooks
+- Context API
+- Basic suspense
+- Controlled components
 ----
 ## Project: Initial VDOM support (TBD)
 > Get the initial VDom + Event System + Patching + Diffing + Component framework up and running
@@ -80,18 +84,25 @@ Welcome to the first iteration of the Dioxus Virtual DOM! This release brings su
 - [x] Tweak macro parsing for better errors
 - [x] dirty tagging, compression
 - [x] code health
+- [ ] name spacing so svg works
+- [ ] fix keys on elements
+- [ ] controlled components (kinda tuff since we need all these different platforms)
+  - [ ] Their own crate
+  - [ ] Re-exported through the `dioxus` crate (not core)
+- [ ] Hooks
+  - [ ] Re-exported through the `dioxus` crate (not essential to core virtualdom)
+
+## Less-essential todos
 - [ ] Make events lazy (use traits + Box<dyn>) - not sure what this means anymore
 - [ ] Beef up the dioxus CLI tool to report build progress
 - [ ] Extract arena logic out for better safety guarantees
 - [ ] Extract BumpFrame logic out for better safety guarantees
 - [ ] make SSR follow HTML spec
-- [ ] fix keys on elements
 - [ ] MIRI tests
 - [ ] all synthetic events filled out
 - [ ] double check event targets and stuff
 - [ ] Documentation overhaul
 - [ ] Website
-- [ ] controlled components
 
 lower priority features
 - [ ] Attributes on elements should implement format_args instead of string fmt

+ 34 - 0
notes/Parity.md

@@ -0,0 +1,34 @@
+# Parity with React
+
+Sorted by priority
+
+| Feature                | Dioxus | React |
+| ---------------------- | ------ | ----- |
+| Conditional Rendering  | ✅     | ✅    |
+| Map, Iterator          | ✅     | ✅    |
+| Keyed Components       | ✅     | ✅    |
+| Web                    | ✅     | ✅    |
+| Desktop (webview)      | ✅     | ✅    |
+| Context                | ✅     | ✅    |
+| Hook                   | ✅     | ✅    |
+| SSR                    | ✅     | ✅    |
+| Runs natively          | ✅     | 👀    |
+| Null components        | 👀     | ✅    |
+| Fragments              | 👀     | ✅    |
+| Component Children     | 👀     | ✅    |
+| NodeRef                | 👀     | ✅    |
+| Controlled Inputs      | 👀     | ✅    |
+| No-div components      | 👀     | ✅    |
+| CSS/Inline Styles      | 👀     | ✅    |
+| 1st class global state | 👀     | ✅    |
+| --------------------   | -----  | ----- |
+| 1st class router       | 👀     | ✅    |
+| Suspense               | 👀     | 👀    |
+| Animation              | 👀     | ✅    |
+| Mobile                 | 👀     | ✅    |
+| Desktop (native)       | 👀     | ✅    |
+| 3D Renderer            | 👀     | ✅    |
+| --------------------   | -----  | ----- |
+| Portal                 | 👀     | ✅    |
+| Error boundary         | 👀     | ✅    |
+| Code-splitting         | 👀     | ✅    |

+ 1 - 1
packages/recoil/Cargo.toml

@@ -8,8 +8,8 @@ edition = "2018"
 
 [dependencies]
 dioxus-core = { path = "../core" }
-uuid = "0.8.2"
 
 [dev-dependencies]
+uuid = { version = "0.8.2", features = ["v4"] }
 dioxus-web = { path = "../web" }
 wasm-bindgen-futures = "*"

+ 19 - 4
packages/recoil/examples/family.rs

@@ -2,16 +2,22 @@ use std::collections::HashMap;
 
 use dioxus_core::prelude::*;
 use recoil::*;
+use uuid::Uuid;
 
-const TODOS: AtomFamily<&str, Todo> = |_| HashMap::new();
+const TODOS: AtomFamily<Uuid, Todo> = |_| HashMap::new();
 
 #[derive(PartialEq)]
 struct Todo {
     checked: bool,
+    title: String,
     contents: String,
 }
 
 static App: FC<()> = |ctx, _| {
+    use_init_recoil_root(ctx);
+
+    let todos = use_recoil_family(ctx, &TODOS);
+
     rsx! { in ctx,
         div {
             "Basic Todolist with AtomFamilies in Recoil.rs"
@@ -19,11 +25,20 @@ static App: FC<()> = |ctx, _| {
     }
 };
 
-static Child: FC<()> = |ctx, _| {
-    // let todo = use_recoil_value(ctx, &TODOS);
+#[derive(Props, PartialEq)]
+struct ChildProps {
+    id: Uuid,
+}
+
+static Child: FC<ChildProps> = |ctx, props| {
+    let (todo, set_todo) = use_recoil_state(ctx, &TODOS.select(&props.id));
+
     rsx! { in ctx,
         div {
-
+            h1 {"{todo.title}"}
+            input { type: "checkbox", name: "scales", checked: "{todo.checked}" }
+            label { "{todo.contents}", for: "scales" }
+            p {"{todo.contents}"}
         }
     }
 };

+ 2 - 1
packages/recoil/examples/selectorlist.rs

@@ -18,8 +18,9 @@ const D_SELECTOR: SelectorFamilyBorrowed<i32, i32> = |api, key| -> &i32 {
 };
 
 static App: FC<()> = |ctx, _| {
-    let title = use_recoil_value(ctx, &C_SELECTOR);
+    use_init_recoil_root(ctx);
 
+    let title = use_recoil_value(ctx, &C_SELECTOR);
     let title = "";
     rsx! { in ctx,
         div {

+ 10 - 5
packages/recoil/src/lib.rs

@@ -43,6 +43,7 @@ pub struct CollectionSelection<T> {
     _never: PhantomData<T>,
 }
 impl<T> Readable<T> for CollectionSelection<T> {}
+impl<T> Writeable<T> for CollectionSelection<T> {}
 
 // =================
 //    Selectors
@@ -125,22 +126,26 @@ mod hooks {
 
     pub fn use_set_state<'a, T: PartialEq>(
         c: Context<'a>,
-        t: &'static impl Writeable<T>,
+        t: &impl Writeable<T>,
     ) -> &'a Rc<dyn Fn(T)> {
         todo!()
     }
 
     pub fn use_recoil_state<'a, T: PartialEq + 'static>(
         ctx: Context<'a>,
-        readable: &'static impl Writeable<T>,
+        writeable: &impl Writeable<T>,
     ) -> (&'a T, &'a Rc<dyn Fn(T)>) {
         todo!()
     }
 
-    pub fn use_recoil_value<'a, T: PartialEq>(
+    pub fn use_recoil_value<'a, T: PartialEq>(ctx: Context<'a>, t: &impl Readable<T>) -> &'a T {
+        todo!()
+    }
+
+    pub fn use_recoil_family<'a, K, V, C: FamilyCollection<K, V>>(
         ctx: Context<'a>,
-        t: &'static impl Readable<T>,
-    ) -> &'a T {
+        t: &AtomFamily<K, V, C>,
+    ) -> &'a C {
         todo!()
     }
 

+ 36 - 38
packages/web/examples/todomvcsingle.rs

@@ -13,16 +13,24 @@ use recoil::*;
 use std::collections::HashMap;
 use uuid::Uuid;
 
-const APP_STYLE: &'static str = include_str!("./todomvc/style.css");
+#[derive(PartialEq, Clone, Copy)]
+pub enum FilterState {
+    All,
+    Active,
+    Completed,
+}
 
-fn main() {
-    wasm_bindgen_futures::spawn_local(dioxus_web::WebsysRenderer::start(App));
+#[derive(Debug, PartialEq, Clone)]
+pub struct TodoItem {
+    pub id: Uuid,
+    pub checked: bool,
+    pub contents: String,
 }
 
 // Declare our global app state
-const TODO_LIST: Atom<HashMap<Uuid, TodoItem>> = atom(|_| Default::default());
-const FILTER: Atom<FilterState> = atom(|_| FilterState::All);
-const TODOS_LEFT: selector<usize> = selector(|api| api.get(&TODO_LIST).len());
+const TODO_LIST: Atom<HashMap<Uuid, TodoItem>> = |_| Default::default();
+const FILTER: Atom<FilterState> = |_| FilterState::All;
+const TODOS_LEFT: Selector<usize> = |api| api.get(&TODO_LIST).len();
 
 // Implement a simple abstraction over sets/gets of multiple atoms
 struct TodoManager(RecoilApi);
@@ -64,32 +72,7 @@ impl TodoManager {
     }
 }
 
-#[derive(PartialEq, Clone, Copy)]
-pub enum FilterState {
-    All,
-    Active,
-    Completed,
-}
-
-#[derive(Debug, PartialEq, Clone)]
-pub struct TodoItem {
-    pub id: Uuid,
-    pub checked: bool,
-    pub contents: String,
-}
-
-fn App(ctx: Context, props: &()) -> DomTree {
-    use_init_recoil_root(ctx);
-
-    rsx! { in ctx,
-        div { id: "app", style { "{APP_STYLE}" }
-            TodoList {}
-            Footer {}
-        }
-    }
-}
-
-pub fn TodoList(ctx: Context, props: &()) -> DomTree {
+pub fn TodoList(ctx: Context, _props: &()) -> DomTree {
     let draft = use_state_new(&ctx, || "".to_string());
     let todos = use_recoil_value(&ctx, &TODO_LIST);
     let filter = use_recoil_value(&ctx, &FILTER);
@@ -154,9 +137,9 @@ pub fn TodoEntry(ctx: Context, props: &TodoEntryProps) -> DomTree {
     ))
 }
 
-pub fn FilterToggles(ctx: Context, props: &()) -> DomTree {
-    let reducer = use_recoil_context::<TodoManager>(ctx);
-    let items_left = use_selector(ctx, &TODOS_LEFT);
+pub fn FilterToggles(ctx: Context, _props: &()) -> DomTree {
+    let reducer = use_recoil_callback(ctx, |api| TodoManager(api));
+    let items_left = use_recoil_value(ctx, &TODOS_LEFT);
 
     let toggles = [
         ("All", "", FilterState::All),
@@ -168,10 +151,9 @@ pub fn FilterToggles(ctx: Context, props: &()) -> DomTree {
         rsx!(
             li {
                 class: "{name}"
-                a {
+                a { "{name}",
                     href: "{path}",
                     onclick: move |_| reducer.set_filter(&filter),
-                    "{name}"
                 }
             }
         )
@@ -196,7 +178,7 @@ pub fn FilterToggles(ctx: Context, props: &()) -> DomTree {
     }
 }
 
-pub fn Footer(ctx: Context, props: &()) -> DomTree {
+pub fn Footer(ctx: Context, _props: &()) -> DomTree {
     rsx! { in ctx,
         footer {
             class: "info"
@@ -212,3 +194,19 @@ pub fn Footer(ctx: Context, props: &()) -> DomTree {
         }
     }
 }
+
+const APP_STYLE: &'static str = include_str!("./todomvc/style.css");
+
+fn App(ctx: Context, _props: &()) -> DomTree {
+    use_init_recoil_root(ctx);
+    rsx! { in ctx,
+        div { id: "app", style { "{APP_STYLE}" }
+            TodoList {}
+            Footer {}
+        }
+    }
+}
+
+fn main() {
+    wasm_bindgen_futures::spawn_local(dioxus_web::WebsysRenderer::start(App));
+}