Prechádzať zdrojové kódy

example: ssr + tide

Jonathan Kelley 4 rokov pred
rodič
commit
269e81b

+ 16 - 7
packages/core/src/virtual_dom.rs

@@ -43,12 +43,12 @@ pub struct VirtualDom {
 
     /// The index of the root component
     /// Should always be the first (gen=0, id=0)
-    pub base_scope: ScopeIdx,
+    pub(crate) base_scope: ScopeIdx,
 
     /// All components dump their updates into a queue to be processed
     pub(crate) event_queue: EventQueue,
 
-    pub tasks: TaskQueue,
+    pub(crate) tasks: TaskQueue,
 
     root_props: std::pin::Pin<Box<dyn std::any::Any>>,
 
@@ -163,12 +163,21 @@ impl VirtualDom {
             _root_prop_type: TypeId::of::<P>(),
         }
     }
-}
 
-// ======================================
-// Private Methods for the VirtualDom
-// ======================================
-impl VirtualDom {
+    pub fn launch_in_place(root: FC<()>) -> Self {
+        let mut s = Self::new(root);
+        s.rebuild_in_place();
+        s
+    }
+
+    /// Creates a new virtualdom and immediately rebuilds it in place, not caring about the RealDom to write into.
+    ///
+    pub fn launch_with_props_in_place<P: Properties + 'static>(root: FC<P>, root_props: P) -> Self {
+        let mut s = Self::new_with_props(root, root_props);
+        s.rebuild_in_place();
+        s
+    }
+
     /// Rebuilds the VirtualDOM from scratch, but uses a "dummy" RealDom.
     ///
     /// Used in contexts where a real copy of the  structure doesn't matter, and the VirtualDOM is the source of truth.

+ 1 - 1
packages/hooks/Cargo.toml

@@ -7,4 +7,4 @@ edition = "2018"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-dioxus-core = { path="../core" }
+dioxus-core = { path = "../core" }

+ 0 - 4
packages/hooks/src/lib.rs

@@ -1,6 +1,2 @@
-use std::collections::HashMap;
-
-use dioxus_core::prelude::*;
-
 mod usestate;
 pub use usestate::{use_state, UseState};

+ 1 - 0
packages/ssr/Cargo.toml

@@ -11,6 +11,7 @@ dioxus-core = { path = "../core", version = "0.1.0", features = ["serialize"] }
 
 
 [dev-dependencies]
+dioxus-hooks = { path = "../hooks" }
 dioxus-html = { path = "../html" }
 tide-websockets = "*"
 thiserror = "1.0.23"

+ 37 - 66
packages/ssr/examples/tide.rs

@@ -1,13 +1,37 @@
 //!
 //!
 //!
-use std::{borrow::Borrow, rc::Rc, sync::Arc};
-
-use async_std::{prelude::*, sync::RwLock};
-use dioxus::{events::on::MouseEvent, virtual_dom::VirtualDom};
+use dioxus::virtual_dom::VirtualDom;
+use dioxus_core as dioxus;
 use dioxus_core::prelude::*;
-use tide::{Body, Request, Response};
-use tide_websockets::{Message, WebSocket};
+use dioxus_hooks::use_state;
+use dioxus_html as dioxus_elements;
+
+use tide::{Request, Response};
+
+#[async_std::main]
+async fn main() -> Result<(), std::io::Error> {
+    let mut app = tide::new();
+
+    app.at("/:name").get(|req: Request<()>| async move {
+        let initial_name: String = req
+            .param("name")
+            .map(|f| f.parse().unwrap_or("...?".to_string()))
+            .unwrap_or("...?".to_string());
+
+        let dom = VirtualDom::launch_with_props_in_place(Example, ExampleProps { initial_name });
+
+        Ok(Response::builder(200)
+            .body(format!("{}", dioxus_ssr::render_root(&dom)))
+            .content_type(tide::http::mime::HTML)
+            .build())
+    });
+
+    println!("Server available at [http://127.0.0.1:8080/bill]");
+    app.listen("127.0.0.1:8080").await?;
+
+    Ok(())
+}
 
 #[derive(PartialEq, Props)]
 struct ExampleProps {
@@ -15,72 +39,19 @@ struct ExampleProps {
 }
 
 static Example: FC<ExampleProps> = |cx| {
-    let dispaly_name = use_state_new(&cx, move || cx.initial_name.clone());
-
-    let buttons = ["Jack", "Jill", "Bob"].iter().map(|name| {
-        rsx!{
-            button {
-                class: "inline-block py-4 px-8 mr-6 leading-none text-white bg-indigo-600 hover:bg-indigo-900 font-semibold rounded shadow"
-                onmouseover: move |_| dispaly_name.set(name.to_string())
-                "{name}"
-            }
-        }
-    });
+    let dispaly_name = use_state(cx, move || cx.initial_name.clone());
 
     cx.render(rsx! {
-        div {
-            class: "py-12 px-4 text-center w-full max-w-2xl mx-auto",
-            // classes: [Some("asd")]
-            // style: {
-            //     a: "asd"
-            //     b: "ad"
-            // }
-            span {
-                class: "text-sm font-semibold"
+        div { class: "py-12 px-4 text-center w-full max-w-2xl mx-auto",
+            span { class: "text-sm font-semibold"
                 "Dioxus Example: Jack and Jill"
             }
-            h2 {
-                class: "text-5xl mt-2 mb-6 leading-tight font-semibold font-heading"
+            h2 { class: "text-5xl mt-2 mb-6 leading-tight font-semibold font-heading"
                 "Hello, {dispaly_name}"
             }
-            {buttons}
+            ul {
+                {(0..10).map(|f| rsx!( li {"Element {f}"} ))}
+            }
         }
     })
 };
-
-const TEMPLATE: &str = include_str!("./template.html");
-
-#[async_std::main]
-async fn main() -> Result<(), std::io::Error> {
-    let mut app = tide::new();
-
-    app.at("/").get(|_| async {
-        Ok(Response::builder(200)
-            .body(TEMPLATE)
-            .content_type(tide::http::mime::HTML)
-            .build())
-    });
-
-    app.at("/session/:name")
-        .get(WebSocket::new(|req: Request<()>, mut stream| async move {
-            let initial_name: String = req.param("name")?.parse().unwrap_or("...?".to_string());
-
-            let mut dom = VirtualDom::new_with_props(Example, ExampleProps { initial_name });
-
-            let edits = dom.rebuild().unwrap();
-            stream.send_json(&edits).await?;
-
-            // while let Some(Ok(Message::Text(input))) = stream.next().await {
-            //     let output: String = input.chars().rev().collect();
-            //     stream
-            //         .send_string(format!("{} | {}", &input, &output))
-            //         .await?;
-            // }
-
-            Ok(())
-        }));
-
-    app.listen("127.0.0.1:8080").await?;
-
-    Ok(())
-}

+ 40 - 11
packages/ssr/src/lib.rs

@@ -6,11 +6,9 @@
 //! API to progress these lifecycle events to generate a fully-mounted Virtual DOM instance which can be renderer in the
 //! `render` method.
 
-use std::fmt::{Arguments, Display, Formatter};
+use std::fmt::{Display, Formatter};
 
-use dioxus_core::prelude::*;
-use dioxus_core::{nodes::VNode, prelude::ScopeIdx, virtual_dom::VirtualDom};
-use std::io::{BufWriter, Result, Write};
+use dioxus_core::{nodes::VNode, virtual_dom::VirtualDom};
 
 pub fn render_root(vdom: &VirtualDom) -> String {
     format!("{:}", TextRenderer::new(vdom))
@@ -18,7 +16,7 @@ pub fn render_root(vdom: &VirtualDom) -> String {
 
 pub struct SsrConfig {
     // currently not supported - control if we indent the HTML output
-    indent: bool,
+    _indent: bool,
 
     // Control if elements are written onto a new line
     newline: bool,
@@ -26,16 +24,16 @@ pub struct SsrConfig {
     // Currently not implemented
     // Don't proceed onto new components. Instead, put the name of the component.
     // TODO: components don't have names :(
-    skip_components: bool,
+    _skip_components: bool,
 }
 
 impl Default for SsrConfig {
     fn default() -> Self {
         Self {
-            indent: false,
+            _indent: false,
 
             newline: false,
-            skip_components: false,
+            _skip_components: false,
         }
     }
 }
@@ -128,10 +126,10 @@ mod tests {
     use super::*;
 
     use dioxus_core as dioxus;
+    use dioxus_core::prelude::*;
     use dioxus_html as dioxus_elements;
 
     const SIMPLE_APP: FC<()> = |cx| {
-        //
         cx.render(rsx!(div {
             "hello world!"
         }))
@@ -156,16 +154,47 @@ mod tests {
         })
     };
 
+    const NESTED_APP: FC<()> = |cx| {
+        cx.render(rsx!(
+            div {
+                SIMPLE_APP {}
+            }
+        ))
+    };
+    const FRAGMENT_APP: FC<()> = |cx| {
+        cx.render(rsx!(
+            div { "f1" }
+            div { "f2" }
+            div { "f3" }
+            div { "f4" }
+        ))
+    };
+
     #[test]
-    fn test_to_string_works() {
+    fn to_string_works() {
         let mut dom = VirtualDom::new(SIMPLE_APP);
         dom.rebuild_in_place().expect("failed to run virtualdom");
         dbg!(render_root(&dom));
     }
 
     #[test]
-    fn test_write_to_file() {
+    fn nested() {
+        let mut dom = VirtualDom::new(NESTED_APP);
+        dom.rebuild_in_place().expect("failed to run virtualdom");
+        dbg!(render_root(&dom));
+    }
+
+    #[test]
+    fn fragment_app() {
+        let mut dom = VirtualDom::new(FRAGMENT_APP);
+        dom.rebuild_in_place().expect("failed to run virtualdom");
+        dbg!(render_root(&dom));
+    }
+
+    #[test]
+    fn write_to_file() {
         use std::fs::File;
+        use std::io::Write;
 
         let mut file = File::create("index.html").unwrap();