Jelajahi Sumber

Clean up more examples

Jonathan Kelley 1 tahun lalu
induk
melakukan
fe12b1062f

+ 1 - 1
examples/calculator.rs

@@ -22,7 +22,7 @@ fn app() -> Element {
     let val = use_signal(|| String::from("0"));
 
     let input_digit = move |num: u8| {
-        if val.get() == "0" {
+        if *val() == "0" {
             val.set(String::new());
         }
 

+ 21 - 29
examples/compose.rs

@@ -2,52 +2,44 @@
 
 use dioxus::prelude::*;
 use futures_util::StreamExt;
+use tokio::sync::mpsc::UnboundedSender;
 
 fn main() {
     dioxus_desktop::launch(app);
 }
 
 fn app() -> Element {
-    let emails_sent = use_signal(Vec::new);
+    let emails_sent = use_signal(|| Vec::new() as Vec<String>);
 
-    let tx = use_coroutine(|mut rx: UnboundedReceiver<String>| {
-        to_owned![emails_sent];
-        async move {
-            while let Some(message) = rx.next().await {
-                emails_sent.write().push(message);
-            }
+    // Wait for responses to the compose channel, and then push them to the emails_sent signal.
+    let tx = use_coroutine(|mut rx: UnboundedReceiver<String>| async move {
+        while let Some(message) = rx.next().await {
+            emails_sent.write().push(message);
         }
     });
 
-    rsx! {
-        div {
-            h1 { "This is your email" }
+    let open_compose_window = move |evt: MouseEvent| {
+        dioxus_desktop::window().new_window(
+            VirtualDom::new_with_props(compose, tx.clone()),
+            Default::default(),
+        )
+    };
 
-            button {
-                onclick: move |_| {
-                    let dom = VirtualDom::new_with_props(compose, ComposeProps { app_tx: tx.clone() });
-                    dioxus_desktop::window().new_window(dom, Default::default());
-                },
-                "Click to compose a new email"
-            }
-
-            ul {
-                for message in emails_sent.read().iter() {
-                    li {
-                        h3 { "email" }
-                        span {"{message}"}
-                    }
+    rsx! {
+        h1 { "This is your email" }
+        button { onclick: open_compose_window, "Click to compose a new email" }
+        ul {
+            for message in emails_sent.read().iter() {
+                li {
+                    h3 { "email" }
+                    span { "{message}" }
                 }
             }
         }
     }
 }
 
-struct ComposeProps {
-    app_tx: Coroutine<String>,
-}
-
-fn compose(cx: Scope<ComposeProps>) -> Element {
+fn compose(receiver: UnboundedSender<String>) -> Element {
     let user_input = use_signal(String::new);
 
     rsx! {

+ 2 - 2
examples/counter.rs

@@ -9,14 +9,14 @@ fn main() {
 
 fn app() -> Element {
     let counters = use_signal(|| vec![0, 0, 0]);
-    let sum: usize = counters.iter().copied().sum();
+    let sum = use_selector(move || counters.read().iter().copied().sum() as usize);
 
     render! {
         div {
             button { onclick: move |_| counters.write().push(0), "Add counter" }
             button { onclick: move |_| { counters.write().pop(); }, "Remove counter" }
             p { "Total: {sum}" }
-            for (i, counter) in counters.iter().enumerate() {
+            for (i, counter) in counters.read().iter().enumerate() {
                 li {
                     button { onclick: move |_| counters.write()[i] -= 1, "-1" }
                     input {

+ 1 - 4
examples/crm.rs

@@ -145,10 +145,7 @@ fn Settings() -> Element {
 
         button {
             class: "pure-button pure-button-primary red",
-            onclick: move |_| {
-                let mut clients = clients.write();
-                clients.clear();
-            },
+            onclick: move |_| clients.write().clear(),
             "Remove all Clients"
         }
 

+ 2 - 2
examples/dog_app.rs

@@ -36,7 +36,7 @@ fn app() -> Element {
                             }
                         }
                     }
-                    div { flex: "50%", BreedPic { breed: breed.to_string() } }
+                    div { flex: "50%", BreedPic { breed } }
                 }
             }
         },
@@ -50,7 +50,7 @@ struct DogApi {
 }
 
 #[component]
-fn BreedPic(breed: String) -> Element {
+fn BreedPic(breed: Signal<String>) -> Element {
     let fut = use_future(|breed| async move {
         reqwest::get(format!("https://dog.ceo/api/breed/{breed}/images/random"))
             .await

+ 0 - 36
examples/drops.rs

@@ -1,36 +0,0 @@
-use dioxus::prelude::*;
-
-fn main() {
-    dioxus_desktop::launch(app);
-}
-
-fn app() -> Element {
-    let count = if cx.generation() % 2 == 0 { 10 } else { 0 };
-
-    println!("Generation: {}", cx.generation());
-
-    if cx.generation() < 10 {
-        cx.needs_update();
-    }
-
-    render! {
-        for _ in 0..count {
-            drop_child {}
-        }
-    }
-}
-
-fn drop_child() -> Element {
-    cx.use_hook(|| Drops);
-    render! {
-        div{}
-    }
-}
-
-struct Drops;
-
-impl Drop for Drops {
-    fn drop(&mut self) {
-        println!("Dropped!");
-    }
-}

+ 1 - 1
examples/file_explorer.rs

@@ -19,7 +19,7 @@ fn main() {
 
 const _STYLE: &str = manganis::mg!(file("./examples/assets/fileexplorer.css"));
 
-fn app(_props: ()) -> Element {
+fn app() -> Element {
     let files = use_signal(Files::new);
 
     rsx! {

+ 1 - 1
examples/generic_component.rs

@@ -19,6 +19,6 @@ struct GenericChildProps<T: Display + PartialEq + Clone + 'static> {
 
 fn generic_child<T: Display + PartialEq + Clone>(props: GenericChildProps<T>) -> Element {
     render! {
-        div { "{&props.data}" }
+        div { "{props.data}" }
     }
 }

+ 257 - 258
examples/rsx_usage.rs

@@ -39,264 +39,263 @@
 //! - Allow top-level fragments
 
 fn main() {
-    dioxus_desktop::launch(App);
-}
-
-use core::{fmt, str::FromStr};
-use std::fmt::Display;
-
-use baller::Baller;
-use dioxus::prelude::*;
-
-#[component]
-fn App() -> Element {
-    let formatting = "formatting!";
-    let formatting_tuple = ("a", "b");
-    let lazy_fmt = format_args!("lazily formatted text");
-    let asd = 123;
-    rsx! {
-        div {
-            // Elements
-            div {}
-            h1 {"Some text"}
-            h1 {"Some text with {formatting}"}
-            h1 {"Formatting basic expressions {formatting_tuple.0} and {formatting_tuple.1}"}
-            h1 {"Formatting without interpolation " {formatting_tuple.0} "and" {formatting_tuple.1} }
-            h2 {
-                "Multiple"
-                "Text"
-                "Blocks"
-                "Use comments as separators in html"
-            }
-            div {
-                h1 {"multiple"}
-                h2 {"nested"}
-                h3 {"elements"}
-            }
-            div {
-                class: "my special div",
-                h1 {"Headers and attributes!"}
-            }
-            div {
-                // pass simple rust expressions in
-                class: lazy_fmt,
-                id: format_args!("attributes can be passed lazily with std::fmt::Arguments"),
-                class: "asd",
-                class: "{asd}",
-                // if statements can be used to conditionally render attributes
-                class: if formatting.contains("form") { "{asd}" },
-                div {
-                    class: {
-                        const WORD: &str = "expressions";
-                        format_args!("Arguments can be passed in through curly braces for complex {WORD}")
-                    }
-                }
-            }
-
-            // Expressions can be used in element position too:
-            {rsx!(p { "More templating!" })},
-
-            // Iterators
-            {(0..10).map(|i| rsx!(li { "{i}" }))},
-
-            // Iterators within expressions
-            {
-                let data = std::collections::HashMap::<&'static str, &'static str>::new();
-                // Iterators *should* have keys when you can provide them.
-                // Keys make your app run faster. Make sure your keys are stable, unique, and predictable.
-                // Using an "ID" associated with your data is a good idea.
-                data.into_iter().map(|(k, v)| rsx!(li { key: "{k}", "{v}" }))
-            }
-
-            // Matching
-            match true {
-                true => rsx!( h1 {"Top text"}),
-                false => rsx!( h1 {"Bottom text"})
-            }
-
-            // Conditional rendering
-            // Dioxus conditional rendering is based around None/Some. We have no special syntax for conditionals.
-            // You can convert a bool condition to rsx! with .then and .or
-            {true.then(|| rsx!(div {}))},
-
-            // Alternatively, you can use the "if" syntax - but both branches must be resolve to Element
-            if false {
-                h1 {"Top text"}
-            } else {
-                h1 {"Bottom text"}
-            }
-
-            // Using optionals for diverging branches
-            // Note that since this is wrapped in curlies, it's interpreted as an expression
-            {if true {
-                Some(rsx!(h1 {"Top text"}))
-            } else {
-                None
-            }}
-
-            // returning "None" without a diverging branch is a bit noisy... but rare in practice
-            {None as Option<()>},
-
-            // can also just use empty fragments
-            Fragment {}
-
-            // Fragments let you insert groups of nodes without a parent.
-            // This lets you make components that insert elements as siblings without a container.
-            div {"A"}
-            Fragment {
-                div {"B"}
-                div {"C"}
-                Fragment {
-                    "D"
-                    Fragment {
-                        "E"
-                        "F"
-                    }
-                }
-            }
-
-            // Components
-            // Can accept any paths
-            // Notice how you still get syntax highlighting and IDE support :)
-            Baller {}
-            baller::Baller {}
-            crate::baller::Baller {}
-
-            // Can take properties
-            Taller { a: "asd" }
-
-            // Can take optional properties
-            Taller { a: "asd" }
-
-            // Can pass in props directly as an expression
-            {
-                let props = TallerProps {a: "hello", children: None };
-                rsx!(Taller { ..props })
-            }
-
-            // Spreading can also be overridden manually
-            Taller {
-                ..TallerProps { a: "ballin!", children: None },
-                a: "not ballin!"
-            }
-
-            // Can take children too!
-            Taller { a: "asd", div {"hello world!"} }
-
-            // This component's props are defined *inline* with the `inline_props` macro
-            WithInline { text: "using functionc all syntax" }
-
-            // Components can be generic too
-            // This component takes i32 type to give you typed input
-            TypedInput::<i32> {}
-
-            // Type inference can be used too
-            TypedInput { initial: 10.0 }
-
-            // geneircs with the `inline_props` macro
-            Label { text: "hello geneirc world!" }
-            Label { text: 99.9 }
-
-            // Lowercase components work too, as long as they are access using a path
-            baller::lowercase_component {}
-
-            // For in-scope lowercase components, use the `self` keyword
-            self::lowercase_helper {}
-
-            // helper functions
-            // Anything that implements IntoVnode can be dropped directly into Rsx
-            {helper("hello world!")}
-
-            // Strings can be supplied directly
-            {String::from("Hello world!")}
-
-            // So can format_args
-            {format_args!("Hello {}!", "world")}
-
-            // Or we can shell out to a helper function
-            {format_dollars(10, 50)}
-        }
-    }
-}
-
-fn format_dollars(dollars: u32, cents: u32) -> String {
-    format!("${dollars}.{cents:02}")
-}
-
-fn helper<'a>(cx: &'a ScopeState, text: &'a str) -> Element {
-    rsx! {
-        p { "{text}" }
-    }
-}
-
-// no_case_check disables PascalCase checking if you *really* want a snake_case component.
-// This will likely be deprecated/removed in a future update that will introduce a more polished linting system,
-// something like Clippy.
-#[component(no_case_check)]
-fn lowercase_helper() -> Element {
-    rsx! {
-        "asd"
-    }
-}
-
-mod baller {
-    use super::*;
-
-    #[component]
-    /// This component totally balls
-    pub fn Baller() -> Element {
-        todo!()
-    }
-
-    // no_case_check disables PascalCase checking if you *really* want a snake_case component.
-    // This will likely be deprecated/removed in a future update that will introduce a more polished linting system,
-    // something like Clippy.
-    #[component(no_case_check)]
-    pub fn lowercase_component() -> Element {
-        rsx! { "look ma, no uppercase" }
-    }
-}
-
-/// Documention for this component is visible within the rsx macro
-#[component]
-pub fn Taller(
-    /// Fields are documented and accessible in rsx!
-    a: &'static str,
-    children: Element,
-) -> Element {
-    rsx! {
-        {&cx.props.children}
-    }
-}
-
-#[derive(Props, PartialEq, Eq)]
-pub struct TypedInputProps<T> {
-    #[props(optional, default)]
-    initial: Option<T>,
-}
-
-#[allow(non_snake_case)]
-pub fn TypedInput<T>(_: Scope<TypedInputProps<T>>) -> Element
-where
-    T: FromStr + fmt::Display,
-    <T as FromStr>::Err: std::fmt::Display,
-{
     todo!()
+    // dioxus_desktop::launch(App);
 }
 
-#[component]
-fn WithInline<'a>(cx: Scope<'a>, text: &'a str) -> Element {
-    rsx! {
-        p { "{text}" }
-    }
-}
-
-#[component]
-fn Label<T>(text: T) -> Element
-where
-    T: Display,
-{
-    rsx! {
-        p { "{text}" }
-    }
-}
+// use core::{fmt, str::FromStr};
+// use std::fmt::Display;
+
+// use baller::Baller;
+// use dioxus::prelude::*;
+
+// #[component]
+// fn App() -> Element {
+//     let formatting = "formatting!";
+//     let formatting_tuple = ("a", "b");
+//     let lazy_fmt = format_args!("lazily formatted text");
+//     let asd = 123;
+//     rsx! {
+//         div {
+//             // Elements
+//             div {}
+//             h1 {"Some text"}
+//             h1 {"Some text with {formatting}"}
+//             h1 {"Formatting basic expressions {formatting_tuple.0} and {formatting_tuple.1}"}
+//             h1 {"Formatting without interpolation " {formatting_tuple.0} "and" {formatting_tuple.1} }
+//             h2 {
+//                 "Multiple"
+//                 "Text"
+//                 "Blocks"
+//                 "Use comments as separators in html"
+//             }
+//             div {
+//                 h1 {"multiple"}
+//                 h2 {"nested"}
+//                 h3 {"elements"}
+//             }
+//             div {
+//                 class: "my special div",
+//                 h1 {"Headers and attributes!"}
+//             }
+//             div {
+//                 // pass simple rust expressions in
+//                 class: lazy_fmt,
+//                 id: format_args!("attributes can be passed lazily with std::fmt::Arguments"),
+//                 class: "asd",
+//                 class: "{asd}",
+//                 // if statements can be used to conditionally render attributes
+//                 class: if formatting.contains("form") { "{asd}" },
+//                 div {
+//                     class: {
+//                         const WORD: &str = "expressions";
+//                         format_args!("Arguments can be passed in through curly braces for complex {WORD}")
+//                     }
+//                 }
+//             }
+
+//             // Expressions can be used in element position too:
+//             {rsx!(p { "More templating!" })},
+
+//             // Iterators
+//             {(0..10).map(|i| rsx!(li { "{i}" }))},
+
+//             // Iterators within expressions
+//             {
+//                 let data = std::collections::HashMap::<&'static str, &'static str>::new();
+//                 // Iterators *should* have keys when you can provide them.
+//                 // Keys make your app run faster. Make sure your keys are stable, unique, and predictable.
+//                 // Using an "ID" associated with your data is a good idea.
+//                 data.into_iter().map(|(k, v)| rsx!(li { key: "{k}", "{v}" }))
+//             }
+
+//             // Matching
+//             match true {
+//                 true => rsx!( h1 {"Top text"}),
+//                 false => rsx!( h1 {"Bottom text"})
+//             }
+
+//             // Conditional rendering
+//             // Dioxus conditional rendering is based around None/Some. We have no special syntax for conditionals.
+//             // You can convert a bool condition to rsx! with .then and .or
+//             {true.then(|| rsx!(div {}))},
+
+//             // Alternatively, you can use the "if" syntax - but both branches must be resolve to Element
+//             if false {
+//                 h1 {"Top text"}
+//             } else {
+//                 h1 {"Bottom text"}
+//             }
+
+//             // Using optionals for diverging branches
+//             // Note that since this is wrapped in curlies, it's interpreted as an expression
+//             {if true {
+//                 Some(rsx!(h1 {"Top text"}))
+//             } else {
+//                 None
+//             }}
+
+//             // returning "None" without a diverging branch is a bit noisy... but rare in practice
+//             {None as Option<()>},
+
+//             // can also just use empty fragments
+//             Fragment {}
+
+//             // Fragments let you insert groups of nodes without a parent.
+//             // This lets you make components that insert elements as siblings without a container.
+//             div {"A"}
+//             Fragment {
+//                 div {"B"}
+//                 div {"C"}
+//                 Fragment {
+//                     "D"
+//                     Fragment {
+//                         "E"
+//                         "F"
+//                     }
+//                 }
+//             }
+
+//             // Components
+//             // Can accept any paths
+//             // Notice how you still get syntax highlighting and IDE support :)
+//             Baller {}
+//             baller::Baller {}
+//             crate::baller::Baller {}
+
+//             // Can take properties
+//             Taller { a: "asd" }
+
+//             // Can take optional properties
+//             Taller { a: "asd" }
+
+//             // Can pass in props directly as an expression
+//             {
+//                 let props = TallerProps {a: "hello", children: None };
+//                 rsx!(Taller { ..props })
+//             }
+
+//             // Spreading can also be overridden manually
+//             Taller {
+//                 ..TallerProps { a: "ballin!", children: None },
+//                 a: "not ballin!"
+//             }
+
+//             // Can take children too!
+//             Taller { a: "asd", div {"hello world!"} }
+
+//             // This component's props are defined *inline* with the `inline_props` macro
+//             WithInline { text: "using functionc all syntax" }
+
+//             // Components can be generic too
+//             // This component takes i32 type to give you typed input
+//             TypedInput::<i32> {}
+
+//             // Type inference can be used too
+//             TypedInput { initial: 10.0 }
+
+//             // geneircs with the `inline_props` macro
+//             Label { text: "hello geneirc world!" }
+//             Label { text: 99.9 }
+
+//             // Lowercase components work too, as long as they are access using a path
+//             baller::lowercase_component {}
+
+//             // For in-scope lowercase components, use the `self` keyword
+//             self::lowercase_helper {}
+
+//             // helper functions
+//             // Anything that implements IntoVnode can be dropped directly into Rsx
+//             {helper("hello world!")}
+
+//             // Strings can be supplied directly
+//             {String::from("Hello world!")}
+
+//             // So can format_args
+//             {format_args!("Hello {}!", "world")}
+
+//             // Or we can shell out to a helper function
+//             {format_dollars(10, 50)}
+//         }
+//     }
+// }
+
+// fn format_dollars(dollars: u32, cents: u32) -> String {
+//     format!("${dollars}.{cents:02}")
+// }
+
+// fn helper<'a>(cx: &'a ScopeState, text: &'a str) -> Element {
+//     rsx! {
+//         p { "{text}" }
+//     }
+// }
+
+// // no_case_check disables PascalCase checking if you *really* want a snake_case component.
+// // This will likely be deprecated/removed in a future update that will introduce a more polished linting system,
+// // something like Clippy.
+// #[component(no_case_check)]
+// fn lowercase_helper() -> Element {
+//     rsx! {
+//         "asd"
+//     }
+// }
+
+// mod baller {
+//     use super::*;
+
+//     #[component]
+//     /// This component totally balls
+//     pub fn Baller() -> Element {
+//         todo!()
+//     }
+
+//     // no_case_check disables PascalCase checking if you *really* want a snake_case component.
+//     // This will likely be deprecated/removed in a future update that will introduce a more polished linting system,
+//     // something like Clippy.
+//     #[component(no_case_check)]
+//     pub fn lowercase_component() -> Element {
+//         rsx! { "look ma, no uppercase" }
+//     }
+// }
+
+// /// Documention for this component is visible within the rsx macro
+// #[component]
+// pub fn Taller(
+//     /// Fields are documented and accessible in rsx!
+//     a: &'static str,
+//     children: Element,
+// ) -> Element {
+//     rsx! { {&children} }
+// }
+
+// #[derive(Props, PartialEq, Eq)]
+// pub struct TypedInputProps<T> {
+//     #[props(optional, default)]
+//     initial: Option<T>,
+// }
+
+// #[allow(non_snake_case)]
+// pub fn TypedInput<T>(_: Scope<TypedInputProps<T>>) -> Element
+// where
+//     T: FromStr + fmt::Display,
+//     <T as FromStr>::Err: std::fmt::Display,
+// {
+//     todo!()
+// }
+
+// #[component]
+// fn WithInline(cx: Scope<'a>, text: &'a str) -> Element {
+//     rsx! {
+//         p { "{text}" }
+//     }
+// }
+
+// #[component]
+// fn Label<T: Clone + PartialEq>(text: T) -> Element
+// where
+//     T: Display,
+// {
+//     rsx! {
+//         p { "{text}" }
+//     }
+// }