diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index 385268ec8..5dc83c9d7 100644 --- a/packages/core/src/virtual_dom.rs +++ b/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>, @@ -163,12 +163,21 @@ impl VirtualDom { _root_prop_type: TypeId::of::

(), } } -} -// ====================================== -// 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(root: FC

, 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. diff --git a/packages/hooks/Cargo.toml b/packages/hooks/Cargo.toml index 40b58a22e..3696a9fa5 100644 --- a/packages/hooks/Cargo.toml +++ b/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" } diff --git a/packages/hooks/src/lib.rs b/packages/hooks/src/lib.rs index 017395172..b3463a950 100644 --- a/packages/hooks/src/lib.rs +++ b/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}; diff --git a/packages/ssr/Cargo.toml b/packages/ssr/Cargo.toml index 3783e6bf9..e53dad3be 100644 --- a/packages/ssr/Cargo.toml +++ b/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" diff --git a/packages/ssr/examples/tide.rs b/packages/ssr/examples/tide.rs index 11edae563..dbed0cd28 100644 --- a/packages/ssr/examples/tide.rs +++ b/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 = |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(()) -} diff --git a/packages/ssr/src/lib.rs b/packages/ssr/src/lib.rs index 38fb8d6b2..c0e0963d2 100644 --- a/packages/ssr/src/lib.rs +++ b/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();