Ver código fonte

wip: more work on updating syntad

Jonathan Kelley 4 anos atrás
pai
commit
47e8960

+ 3 - 2
Cargo.toml

@@ -6,9 +6,10 @@ members = [
     "packages/web",
     "packages/dioxus",
     "packages/ssr",
+    "packages/docsite",
+    "packages/recoil",
+    "packages/router",
 ]
-# "packages/recoil",
-# "packages/docsite",
 # "packages/webview",
 
 # "packages/cli",

+ 2 - 2
README.md

@@ -8,7 +8,7 @@
 Dioxus is a portable, performant, and ergonomic framework for building cross-platform user experiences in Rust.
 
 ```rust
-fn Example(ctx: Context<()>) -> VNodes {
+fn Example(ctx: Context<()>) -> VNode {
     let (selection, set_selection) = use_state(&ctx, || "..?");
 
     ctx.render(rsx! {
@@ -41,7 +41,7 @@ If you know React, then you already know Dioxus.
         <th><a href="http://github.com/jkelleyrtp/dioxus">Web</a></th>
         <th><a href="http://github.com/jkelleyrtp/dioxus">Desktop</a></th>
         <th><a href="http://github.com/jkelleyrtp/dioxus">Mobile</a></th>
-        <th><a href="http://github.com/jkelleyrtp/dioxus">State Management</a></th>
+        <th><a href="http://github.com/jkelleyrtp/dioxus">State</a></th>
         <th><a href="http://github.com/jkelleyrtp/dioxus">Docs</a></th>
         <th><a href="http://github.com/jkelleyrtp/dioxus">Tools</a></th>
     <tr>

+ 0 - 0
packages/docsite/src/components/app.rs → packages/core/examples/app.rs


+ 12 - 0
packages/core/src/virtual_dom.rs

@@ -314,6 +314,10 @@ impl VirtualDom {
 
         Ok(())
     }
+
+    pub fn base_scope(&self) -> &Scope {
+        todo!()
+    }
 }
 
 // TODO!
@@ -802,6 +806,14 @@ Any function prefixed with "use" should not be called conditionally.
             |_| {},
         )
     }
+
+    fn suspend<O>(
+        &self,
+        f: impl Future<Output = O>,
+        g: impl FnOnce(O) -> VNode<'src> + 'src,
+    ) -> VNode<'src> {
+        todo!()
+    }
 }
 
 // ==================================================================================

+ 17 - 0
packages/docsite/src/blah.html

@@ -0,0 +1,17 @@
+<svg
+  x="0px"
+  y="0px"
+  viewBox="0 0 100 100"
+  width="15"
+  height="15"
+  class="css-83uoqv"
+>
+  <path
+    fill="currentColor"
+    d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0, 0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"
+  ></path>
+  <polygon
+    fill="currentColor"
+    points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"
+  ></polygon>
+</svg>

+ 9 - 0
packages/docsite/src/components/blog.rs

@@ -0,0 +1,9 @@
+use dioxus_ssr::prelude::*;
+
+pub static Blog: FC<()> = |ctx| {
+    rsx! { in ctx,
+        div {
+
+        }
+    }
+};

+ 9 - 0
packages/docsite/src/components/community.rs

@@ -0,0 +1,9 @@
+use dioxus_ssr::prelude::*;
+
+pub static Community: FC<()> = |ctx| {
+    rsx! { in ctx,
+        div {
+
+        }
+    }
+};

+ 9 - 0
packages/docsite/src/components/docs.rs

@@ -0,0 +1,9 @@
+use dioxus_ssr::prelude::*;
+
+pub static Docs: FC<()> = |ctx| {
+    rsx! { in ctx,
+        div {
+
+        }
+    }
+};

+ 42 - 0
packages/docsite/src/components/homepage.rs

@@ -0,0 +1,42 @@
+use dioxus_ssr::prelude::*;
+
+const HeroContent: [(&'static str, &'static str); 3] = [
+    ("Declarative", 
+    "React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes.\nDeclarative views make your code more predictable and easier to debug."),
+
+    ("Component-Based", "Build encapsulated components that manage their own state, then compose them to make complex UIs.\nSince component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep state out of the DOM."),
+
+    ("Learn Once, Write Anywhere", "We don’t make assumptions about the rest of your technology stack, so you can develop new features in React without rewriting existing code.\nReact can also render on the server using Node and power mobile apps using React Native."),
+];
+
+const SnippetHighlights: &'static str = include_str!("./../snippets.md");
+
+pub static Home: FC<()> = |ctx| {
+    let hero = HeroContent.iter().map(|(title, body)| {
+        rsx! {
+            div {
+                h3 { "{title}" }
+                div { {body.split("\n").map(|paragraph| rsx!( p{"{paragraph}"} ))} }
+            }
+        }
+    });
+    let snippets: Vec<VNode> = crate::utils::markdown_to_snippet(ctx, SnippetHighlights);
+
+    rsx! { in ctx,
+        div {
+            header {
+                // Hero
+                section {
+                    div { {hero} }
+                }
+                hr {}
+                // Highlighted Snippets
+                section {
+                    {snippets}
+                }
+            }
+            div {}
+            section {}
+        }
+    }
+};

+ 9 - 0
packages/docsite/src/components/tutorial.rs

@@ -0,0 +1,9 @@
+use dioxus_ssr::prelude::*;
+
+pub static Tutorial: FC<()> = |ctx| {
+    rsx! { in ctx,
+        div {
+
+        }
+    }
+};

+ 126 - 71
packages/docsite/src/main.rs

@@ -1,97 +1,152 @@
 #![allow(non_upper_case_globals)]
 
-use dioxus_ssr::{
-    prelude::*,
-    prelude::{builder::IntoVNode, dioxus::events::on::MouseEvent},
-    TextRenderer,
-};
-mod utils;
+use dioxus_ssr::{prelude::*, TextRenderer};
+pub mod utils;
+mod components {
+    mod community;
+    pub use community::*;
+    mod docs;
+    pub use docs::*;
+    mod blog;
+    pub use blog::*;
+    mod homepage;
+    pub use homepage::*;
+    mod tutorial;
+    pub use tutorial::*;
+}
+use components::*;
 
 fn main() {
     let renderer = TextRenderer::new(App);
+    /*
+    renderer.render_at("community")
+
+    */
 }
 
 static App: FC<()> = |ctx| {
-    rsx! { in ctx,
+    let (url, set_url) = use_state(&ctx, || "");
+
+    let body = match *url {
+        "community" => rsx!(in ctx, Community {}),
+        "tutorial" => rsx!(in ctx, Tutorial {}),
+        "blog" => rsx!(in ctx, Blog {}),
+        "docs" => rsx!(in ctx, Docs {}),
+        _ => rsx!(in ctx, Home {}),
+    };
+
+    ctx.render(rsx! {
         div {
-            Home {}
-            Docs {}
-            Tutorial {}
-            Blog {}
-            Community {}
+            NavBar {}
+            {body}
+            Footer {}
         }
-    }
+    })
 };
 
-const HeroContent: [(&'static str, &'static str); 3] = [
-    ("Declarative", 
-    "React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes.\nDeclarative views make your code more predictable and easier to debug."),
-
-    ("Component-Based", "Build encapsulated components that manage their own state, then compose them to make complex UIs.\nSince component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep state out of the DOM."),
+static NavBar: FC<()> = |ctx| {
+    ctx.render(rsx! {
+        header {
+            a {
+                href: "/"
+                img { /*logo*/ }
+                span {}
+            }
+            nav {
+                a { href: "/community/support", "Community" }
+                a { href: "/docs/getting-started", "Docs" }
+                a { href: "/tutorial/tutorial", "Tutorial" }
+                a { href: "/blog/", "Blog" }
+            }
+            form {}
+            div {}
+        }
+    })
+};
 
-    ("Learn Once, Write Anywhere", "We don’t make assumptions about the rest of your technology stack, so you can develop new features in React without rewriting existing code.\nReact can also render on the server using Node and power mobile apps using React Native."),
+static SECTIONS: &[(&str, &[(&str, &str)])] = &[
+    (
+        "Docs",
+        &[
+            ("Installation", "docs/installation"),
+            ("Main Concepts", "docs/main"),
+            ("Advanced Guides", "docs/advanced"),
+            ("Hooks", "docs/hooks"),
+            ("Testing", "docs/testing"),
+            ("Contributing", "docs/contributing"),
+            ("FAQ", "docs/faq"),
+        ],
+    ),
+    (
+        "Channels",
+        &[("Github", "https://github.com/jkelleyrtp/dioxus")],
+    ),
+    (
+        "Community",
+        &[
+            ("Code of Conduct", "docs/installation"),
+            ("Community Resources", "docs/main"),
+        ],
+    ),
+    (
+        "More",
+        &[
+            ("Tutorial", "docs/installation"),
+            ("Blog", "docs/main"),
+            ("Privacy", "docs/advanced"),
+            ("Terms", "docs/hooks"),
+        ],
+    ),
 ];
 
-const SnippetHighlights: &'static str = include_str!("./snippets.md");
-
-static Home: FC<()> = |ctx| {
-    let hero = HeroContent.iter().map(|(title, body)| {
+fn Footer(ctx: Context<()>) -> VNode {
+    let sections = SECTIONS.iter().map(|(section, raw_links)| {
+        let links = raw_links.iter().map(|(link_name, href)| {
+            rsx! (
+                a { href: "{href}",
+                    "{link_name}",
+                    {href.starts_with("http").then(|| rsx!( ExternalLinkIcon {} ))}
+                }
+            )
+        });
         rsx! {
             div {
-                h3 { "{title}" }
-                div { {body.split("\n").map(|paragraph| rsx!( p{"{paragraph}"} ))} }
+                div { "{section}" }
+                {links}
             }
         }
     });
-    let snippets: Vec<VNode> = utils::markdown_to_snippet(ctx, SnippetHighlights);
 
-    rsx! { in ctx,
-        div {
-            header {
-                // Hero
-                section {
-                    div { {hero} }
-                }
-                hr {}
-                // Highlighted Snippets
-                section {
-                    {snippets}
+    ctx.render(rsx! {
+        footer {
+            div {
+                div {
+                    div {
+                        {sections}
+                    }
+                    section {
+                        a {
+                            img {}
+                        }
+                        p {}
+                    }
                 }
             }
-            div {}
-            section {}
         }
-    }
-};
-
-static Docs: FC<()> = |ctx| {
-    rsx! { in ctx,
-        div {
-
-        }
-    }
-};
-
-static Tutorial: FC<()> = |ctx| {
-    rsx! { in ctx,
-        div {
-
-        }
-    }
-};
-
-static Blog: FC<()> = |ctx| {
-    rsx! { in ctx,
-        div {
-
-        }
-    }
-};
-
-static Community: FC<()> = |ctx| {
-    rsx! { in ctx,
-        div {
+    })
+}
 
-        }
-    }
+const ExternalLinkIcon: FC<()> = |ctx| {
+    ctx.render(html! {
+        <svg x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15">
+            <path
+                fill="currentColor"
+                d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0, 0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"
+            ></path>
+            <polygon
+                fill="currentColor"
+                points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"
+            ></polygon>
+        </svg>
+    })
 };

+ 1 - 1
packages/recoil/.vscode/settings.json

@@ -1,3 +1,3 @@
 {
-    "rust-analyzer.inlayHints.enable": true
+    "rust-analyzer.inlayHints.enable": false
 }

+ 1 - 0
packages/recoil/Cargo.toml

@@ -12,6 +12,7 @@ dioxus-core = { path = "../core" }
 thiserror = "1.0.24"
 log = "0.4.14"
 im-rc = "15.0.0"
+futures = "0.3.15"
 
 [dev-dependencies]
 uuid = { version = "0.8.2", features = ["v4", "wasm-bindgen"] }

+ 3 - 3
packages/recoil/examples/api_mvc.rs

@@ -29,9 +29,9 @@ impl TitleController {
 
 fn main() {
     wasm_bindgen_futures::spawn_local(dioxus_web::WebsysRenderer::start(|ctx| {
-        let title = use_read(ctx, &TITLE);
-        let subtitle = use_read(ctx, &SUBTITLE);
-        let controller = use_recoil_api(ctx, TitleController::new);
+        let title = use_read(&ctx, &TITLE);
+        let subtitle = use_read(&ctx, &SUBTITLE);
+        let controller = TitleController::new(use_recoil_api(&ctx));
 
         rsx! { in ctx,
             div {

+ 1 - 1
packages/recoil/examples/callback.rs

@@ -21,7 +21,7 @@ fn update_title(api: &RecoilApi) {
 
 static App: FC<()> = |ctx| {
     let title = use_read(&ctx, &TITLE);
-    let next_light = use_recoil_api(ctx, |api| move |_| update_title(&api));
+    let next_light = use_recoil_api(&ctx, |api| move |_| update_title(&api));
 
     rsx! { in ctx,
         div {

+ 1 - 1
packages/recoil/examples/familypoc.rs

@@ -14,7 +14,7 @@ struct Todo {
 
 static App: FC<()> = |ctx| {
     use_init_recoil_root(ctx, |_| {});
-    let todos = use_read(ctx, &TODOS);
+    let todos = use_read(&ctx, &TODOS);
 
     rsx! { in ctx,
         div {

+ 1 - 1
packages/recoil/examples/hellorecoil.rs

@@ -6,7 +6,7 @@ const COUNT: Atom<i32> = |_| 0;
 static App: FC<()> = |ctx| {
     use_init_recoil_root(ctx, |_| {});
 
-    let (count, set_count) = use_read_write(ctx, &COUNT);
+    let (count, set_count) = use_read_write(&ctx, &COUNT);
 
     rsx! { in ctx,
         div {

+ 3 - 3
packages/recoil/examples/selectors.rs

@@ -17,12 +17,12 @@ static App: FC<()> = |ctx| {
 };
 
 static Banner: FC<()> = |ctx| {
-    let count = use_read(ctx, &C);
+    let count = use_read(&ctx, &C);
     ctx.render(rsx! { h1 { "Count: {count}" } })
 };
 
 static BtnA: FC<()> = |ctx| {
-    let (a, set) = use_read_write(ctx, &A);
+    let (a, set) = use_read_write(&ctx, &A);
     rsx! { in ctx,
         div { "a"
             button { "+", onclick: move |_| set(a + 1) }
@@ -32,7 +32,7 @@ static BtnA: FC<()> = |ctx| {
 };
 
 static BtnB: FC<()> = |ctx| {
-    let (b, set) = use_read_write(ctx, &B);
+    let (b, set) = use_read_write(&ctx, &B);
     rsx! { in ctx,
         div { "b"
             button { "+", onclick: move |_| set(b + 1) }

+ 50 - 0
packages/recoil/examples/supense_integration.rs

@@ -0,0 +1,50 @@
+// const Posts: AtomFamily = |family| {
+//     family.on_get(|key| {
+
+//         //
+//     })
+// };
+
+fn main() {
+    wasm_bindgen_futures::spawn_local(dioxus_web::WebsysRenderer::start(App))
+}
+
+use std::future::Future;
+
+use dioxus_core::prelude::*;
+
+static App: FC<()> = |ctx| {
+    //
+
+    let title = use_async_atom();
+    let title_card = suspend(&ctx, title, move |val| {
+        //
+        rsx!(in ctx, div {
+            h3 { "{val}" }
+        })
+    });
+
+    // let fut = (use_async_atom(), use_async_atom());
+    // let title_card2 = ctx.suspend(fut, move |(text, text2)| {
+    //     ctx.render(rsx!( h3 { "{text}" } ))
+    // });
+
+    ctx.render(rsx! {
+        div {
+            {title_card}
+            // {title_card2}
+        }
+    })
+};
+
+async fn use_async_atom() -> String {
+    todo!()
+}
+
+fn suspend<'a, O>(
+    c: &impl Scoped<'a>,
+    f: impl Future<Output = O>,
+    g: impl FnOnce(O) -> VNode<'a> + 'a,
+) -> VNode<'a> {
+    todo!()
+}

+ 2 - 0
packages/recoil/src/lib.rs

@@ -525,6 +525,8 @@ mod utils {
     use super::*;
     use dioxus_core::prelude::*;
 
+    pub struct RecoilApi {}
+
     /// This tiny util wraps your main component with the initializer for the recoil root.
     /// This is useful for small programs and the examples in this crate
     pub fn RecoilApp<T: 'static>(

+ 17 - 22
packages/router/README.md

@@ -4,7 +4,7 @@ Dioxus-router provides a use_router hook that returns a different value dependin
 The router is generic over any value, however it makes sense to return a different set of VNodes
 and feed them into the App's return VNodes.
 
-Using the router should feel similar to tide's routing framework where an "address" book is assembled at the head.
+Using the router should feel similar to tide's routing framework where an "address" book is assembled at the head of the app.
 
 Here's an example of how to use the router hook:
 
@@ -13,32 +13,27 @@ static App: FC<()> = |ctx| {
 
     // Route returns the associated VNodes
     // This hook re-fires when the route changes
-    let route = use_router(ctx, |cfg| {
-        cfg.at("/").serve(|ctx| {
-            html!{ <LandingPage /> }
+    let route = use_router(ctx, |router| {
+        router.at("/").get(|path| {
+            rsx!{ <LandingPage /> }
         });
-
-        cfg.at("/shoes/:id").serve(|ctx| {
-            let id: Uuid = ctx.ctx.parse().unwrap();
-            html!{ <ShoesPage id=id /> }
+        router.at("/shoes/:id").get(|path| {
+            let id: Uuid = path.parse().unwrap();
+            rsx!{ <ShoesPage id=id /> }
         });
-
-        cfg.at("/pants/:id").serve(|ctx| {
-            let id: Uuid = ctx.ctx.parse().unwrap();
-            html!{ <PantsPage id=id /> }
+        router.at("/pants/:id").get(|path| {
+            let id: Uuid = path.parse().unwrap();
+            rsx!{ <PantsPage id=id /> }
         });
     });
 
-    html! {
-        <PanicBoundary model={|_| html!{<div>"Uh oh!"</div>}}>
-            <StateManager>
-                <ThemeSystem>
-                    <Header />
-                    {route}
-                </ThemeSystem>
-            </StateManager>
-        </PanicBoundary >
-    }
+    ctx.render(rsx!{
+        div {
+            Navbar {}
+            {route}
+            Footer {}
+        }
+    })
 };
 ```
 

+ 5 - 3
packages/ssr/src/tostring.rs

@@ -34,10 +34,11 @@ fn html_render(
             write!(f, "\n</{}>", el.tag_name)?;
             Ok(())
         }
-        VNode::Text(t) => write!(f, "{}", t.text),
+        VNode::Text(text) => write!(f, "{}", text),
         VNode::Suspended => todo!(),
         VNode::Component(vcomp) => {
-            let id = vcomp.ass_scope.as_ref().borrow().unwrap();
+            let id = vcomp.ass_scope.borrow().unwrap();
+            // let id = vcomp.ass_scope.as_ref().borrow().unwrap();
             let new_node = dom
                 .components
                 .try_get(id)
@@ -46,6 +47,7 @@ fn html_render(
                 .current_head_node();
             html_render(&dom, new_node, f)
         }
+        VNode::Fragment(_) => todo!(),
     }
 }
 
@@ -61,7 +63,7 @@ fn test_serialize() {
                 {(0..20).map(|f| rsx!{
                     div {
                         title: "About W3Schools"
-                        style: "color:blue;text-align:center"
+                        // style: "color:blue;text-align:center"
                         class: "About W3Schools"
                         p {
                             title: "About W3Schools"

+ 8 - 1
packages/web/Cargo.toml

@@ -28,6 +28,7 @@ recoil = { path = "../recoil" }
 # html-validation = { path = "../html-validation", version = "0.1.1" }
 
 async-channel = "1.6.1"
+wee_alloc = "0.4.5"
 # futures-lite = "1.11.3"
 
 [dependencies.web-sys]
@@ -62,7 +63,13 @@ features = [
 ]
 
 [profile.release]
-debug = true
+lto = true
+opt-level = 's'
+
+# debug = true
+
+# [profile.release]
+
 
 [lib]
 crate-type = ["cdylib", "rlib"]

+ 29 - 0
packages/web/examples/basic.rs

@@ -37,3 +37,32 @@ static C2: FC<()> = |ctx| {
         }
     })
 };
+
+static DocExamples: FC<()> = |ctx| {
+    //
+
+    let is_ready = false;
+
+    let items = (0..10).map(|i| rsx! { li {"{i}"} });
+    let _ = rsx! {
+        ul {
+            {items}
+        }
+    };
+
+    rsx! {
+        div {}
+        h1 {}
+        {""}
+        "asbasd"
+        dioxus::Fragment {
+            //
+        }
+    }
+
+    ctx.render(rsx! {
+        div {
+            { is_ready.then(|| rsx!{ h1 {"We are ready!"} }) }
+        }
+    })
+};

+ 5 - 2
packages/web/examples/derive.rs

@@ -8,14 +8,17 @@ fn main() {
     wasm_bindgen_futures::spawn_local(WebsysRenderer::start(App));
 }
 
+// Use `wee_alloc` as the global allocator.
+#[global_allocator]
+static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
+
 fn App(ctx: Context<()>) -> VNode {
     let cansee = use_state_new(&ctx, || false);
     rsx! { in ctx,
         div {
             "Shadow of the child:"
-            button {
+            button { onclick: move |_| cansee.set(!**cansee)
                 "Gaze into the void"
-                onclick: move |_| cansee.set(!**cansee)
             }
             {cansee.then(|| rsx!{ Child {} })}
         }

+ 9 - 15
packages/web/examples/landingpage2.rs

@@ -1,13 +1,14 @@
 //! Basic example that renders a simple VNode to the browser.
 
-use std::rc::Rc;
+use std::{future::Future, pin::Pin, rc::Rc};
 
 use dioxus_core::prelude::*;
 use dioxus_web::*;
 fn main() {
-    // Setup logging
+    // Setup logging and panic handling
     wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
     console_error_panic_hook::set_once();
+
     // Run the app
     wasm_bindgen_futures::spawn_local(WebsysRenderer::start(App));
 }
@@ -16,23 +17,16 @@ static App: FC<()> = |ctx| {
     let (contents, set_contents) = use_state(&ctx, || "asd");
 
     ctx.render(rsx! {
-        div  {
-            class: "flex items-center justify-center flex-col"
-            div {
-                class: "flex items-center justify-center"
-                div {
-                    class: "flex flex-col bg-white rounded p-4 w-full max-w-xs"
+        div  { class: "flex items-center justify-center flex-col"
+            div { class: "flex items-center justify-center"
+                div { class: "flex flex-col bg-white rounded p-4 w-full max-w-xs"
                     div { class: "font-bold text-xl", "Example Web app" }
                     div { class: "text-sm text-gray-500", "This is running in your browser!" }
-                    div {
-                        class: "flex flex-row items-center justify-center mt-6"
+                    div { class: "flex flex-row items-center justify-center mt-6"
                         div { class: "font-medium text-6xl", "100%" }
                     }
-                    div {
-                        class: "flex flex-row justify-between mt-6"
-                        a {
-                            href: "https://www.dioxuslabs.com"
-                            class: "underline"
+                    div { class: "flex flex-row justify-between mt-6"
+                        a { href: "https://www.dioxuslabs.com", class: "underline"
                             "Made with dioxus"
                         }
                     }

+ 1 - 13
packages/web/examples/list.rs

@@ -28,17 +28,10 @@ pub struct TodoItem {
 static App: FC<()> = |ctx| {
     let (draft, set_draft) = use_state(&ctx, || "".to_string());
     let (filter, set_filter) = use_state(&ctx, || FilterState::All);
-    let (is_editing, set_is_editing) = use_state(&ctx, || false);
-    // let (todos, set_todos) = use_state(&ctx, || BTreeMap::<String, TodoItem>::new());
-
-    // let todos = use_ref(&ctx, || BTreeMap::<String, TodoItem>::new());
     let todos = use_state_new(&ctx, || BTreeMap::<uuid::Uuid, TodoItem>::new());
-
-    // let blah = "{draft}"
     ctx.render(rsx!(
         div {
             id: "app"
-
             div {
                 header {
                     class: "header"
@@ -60,7 +53,6 @@ static App: FC<()> = |ctx| {
                     input {
                         class: "new-todo"
                         placeholder: "What needs to be done?"
-                        // value: "{draft}"
                         oninput: move |evt| set_draft(evt.value)
                     }
                 }
@@ -76,17 +68,13 @@ static App: FC<()> = |ctx| {
                     .map(|(id, todo)| {
                         rsx!{
                             li {
+                                key: "{id}"
                                 "{todo.contents}"
                                 input {
                                     class: "toggle"
                                     type: "checkbox"
                                     "{todo.checked}"
                                 }
-                                // {is_editing.then(|| rsx!(
-                                //     input {
-                                //         value: "{contents}"
-                                //     }
-                                // ))}
                             }
                         }
                     })