From 1c4e1d84eabe9ee0638ade77e5ce9da68fb2d912 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 2 Feb 2024 17:21:58 -0600 Subject: [PATCH] serialize data in the server and deserialize data in the client --- packages/fullstack/Cargo.toml | 1 - .../examples/axum-hello-world/Cargo.toml | 2 +- .../examples/axum-hello-world/src/main.rs | 2 ++ packages/fullstack/src/hooks/server_future.rs | 30 ++++++++++--------- .../fullstack/src/html_storage/deserialize.rs | 14 ++++----- 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/packages/fullstack/Cargo.toml b/packages/fullstack/Cargo.toml index 4f608a512..377ba48a1 100644 --- a/packages/fullstack/Cargo.toml +++ b/packages/fullstack/Cargo.toml @@ -69,7 +69,6 @@ dioxus-cli-config = { workspace = true, optional = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] dioxus-hot-reload = { workspace = true } - [features] default = ["hot-reload"] hot-reload = ["serde_json", "futures-util"] diff --git a/packages/fullstack/examples/axum-hello-world/Cargo.toml b/packages/fullstack/examples/axum-hello-world/Cargo.toml index 3d2baf3f0..00a28e795 100644 --- a/packages/fullstack/examples/axum-hello-world/Cargo.toml +++ b/packages/fullstack/examples/axum-hello-world/Cargo.toml @@ -17,5 +17,5 @@ reqwest = "0.11.18" [features] default = [] -ssr = ["dioxus/axum"] +server = ["dioxus/axum"] web = ["dioxus/web"] diff --git a/packages/fullstack/examples/axum-hello-world/src/main.rs b/packages/fullstack/examples/axum-hello-world/src/main.rs index f5ed24b37..5b2cbb03c 100644 --- a/packages/fullstack/examples/axum-hello-world/src/main.rs +++ b/packages/fullstack/examples/axum-hello-world/src/main.rs @@ -11,6 +11,7 @@ use serde::{Deserialize, Serialize}; fn app() -> Element { let mut count = use_signal(|| 0); let text = use_signal(|| "...".to_string()); + let server_future = use_server_future(get_server_data)?; rsx! { h1 { "High-Five counter: {count}" } @@ -30,6 +31,7 @@ fn app() -> Element { "Run a server function!" } "Server said: {text}" + "{server_future.state():?}" } } diff --git a/packages/fullstack/src/hooks/server_future.rs b/packages/fullstack/src/hooks/server_future.rs index a34929231..449f5002d 100644 --- a/packages/fullstack/src/hooks/server_future.rs +++ b/packages/fullstack/src/hooks/server_future.rs @@ -10,7 +10,7 @@ where F: Future + 'static, { let mut cb = use_callback(_future); - let mut gen = use_hook(|| CopyValue::new(0)); + let mut first_run = use_hook(|| CopyValue::new(true)); let resource = use_resource(move || { async move { @@ -18,11 +18,13 @@ where // We're doing this regardless so inputs get tracked, even if we drop the future before polling it let user_fut = cb.call(); - // If this is the first run, the data might be cached - if gen() == 0 { - #[cfg(not(feature = "web"))] + // If this is the first run and we are on the web client, the data might be cached + if *first_run.peek() { + // This is no longer the first run + first_run.set(false); + + #[cfg(feature = "web")] if let Some(o) = crate::html_storage::deserialize::take_server_data::() { - gen.set(1); return o; } } @@ -30,28 +32,28 @@ where // Otherwise just run the future itself let out = user_fut.await; - // and push the gen forward - gen.set(1); + // If this is the first run and we are on the server, cache the data + #[cfg(feature = "ssr")] + if *first_run.peek() { + let _ = crate::server_context::server_context().push_html_data(&out); + } + #[allow(clippy::let_and_return)] out } }); // On the first run, force this task to be polled right away in case its value is ready use_hook(|| { - let _ = resource.task().unwrap().poll_now(); + let _ = resource.task().poll_now(); }); // Suspend if the value isn't ready - match resource.state() { + match resource.state().cloned() { UseResourceState::Pending => { suspend(); None } - UseResourceState::Regenerating => { - suspend(); - Some(resource) - } - UseResourceState::Ready => Some(resource), + _ => Some(resource), } } diff --git a/packages/fullstack/src/html_storage/deserialize.rs b/packages/fullstack/src/html_storage/deserialize.rs index 147f0d237..2280d5f93 100644 --- a/packages/fullstack/src/html_storage/deserialize.rs +++ b/packages/fullstack/src/html_storage/deserialize.rs @@ -26,7 +26,7 @@ pub(crate) fn serde_from_bytes(string: &[u8]) -> Option static SERVER_DATA: once_cell::sync::Lazy> = once_cell::sync::Lazy::new(|| { - #[cfg(target_arch = "wasm32")] + #[cfg(all(feature = "web", target_arch = "wasm32"))] { let window = web_sys::window()?.document()?; let element = match window.get_element_by_id("dioxus-storage-data") { @@ -48,7 +48,7 @@ static SERVER_DATA: once_cell::sync::Lazy> = Some(data.cursor()) } - #[cfg(not(target_arch = "wasm32"))] + #[cfg(not(all(feature = "web", target_arch = "wasm32")))] { None } @@ -63,11 +63,7 @@ pub(crate) fn take_server_data() -> Option { /// /// When dioxus-fullstack renders the page, it will serialize the root props and put them in the document. This function gets them from the document. pub fn get_root_props_from_document() -> Option { - #[cfg(not(target_arch = "wasm32"))] - { - None - } - #[cfg(target_arch = "wasm32")] + #[cfg(all(feature = "web", target_arch = "wasm32"))] { let attribute = web_sys::window()? .document()? @@ -76,4 +72,8 @@ pub fn get_root_props_from_document() -> Option { serde_from_bytes(attribute.as_bytes()) } + #[cfg(not(all(feature = "web", target_arch = "wasm32")))] + { + None + } }