mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
<Suspense/> streaming and hydration issue
This commit is contained in:
parent
c463579faa
commit
3ef64bd372
3 changed files with 51 additions and 30 deletions
|
@ -13,6 +13,8 @@ actix-files = { version = "0.6", optional = true }
|
|||
wasm-bindgen = { version = "0.2", optional = true}
|
||||
console_error_panic_hook = "0.1.7"
|
||||
cfg-if = "1.0.0"
|
||||
gloo-timers = { version = "0.2", features = ["futures"] }
|
||||
futures = "0.3"
|
||||
|
||||
[features]
|
||||
default = ["ssr"]
|
||||
|
|
|
@ -3,24 +3,43 @@
|
|||
use leptos::*;
|
||||
|
||||
#[component]
|
||||
pub fn App(cx: Scope) -> View {
|
||||
pub fn App(cx: Scope) -> impl IntoView {
|
||||
let pending_thing = create_resource(
|
||||
cx,
|
||||
|| (),
|
||||
|_| async {
|
||||
if cfg!(feature = "ssr") {
|
||||
let (tx, rx) = futures::channel::oneshot::channel();
|
||||
spawn_local(async {
|
||||
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||
tx.send(());
|
||||
});
|
||||
rx.await;
|
||||
} else {
|
||||
|
||||
}
|
||||
()
|
||||
}
|
||||
);
|
||||
|
||||
view! { cx,
|
||||
<>
|
||||
<div>
|
||||
"This is some text"
|
||||
</div>
|
||||
<ComponentA>
|
||||
<div>"Hello!"</div>
|
||||
</ComponentA>
|
||||
<Suspense fallback=move || view! { cx, <p>"Loading..."</p> }>
|
||||
{move || pending_thing.read().map(|n| view! { cx, <p>"Loaded."</p>})}
|
||||
</Suspense>
|
||||
</>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn ComponentA(cx: Scope, children: Box<dyn Fn() -> Vec<View>>) -> View {
|
||||
pub fn ComponentA(cx: Scope, children: Box<dyn Fn() -> Vec<View>>) -> impl IntoView {
|
||||
let (value, set_value) = create_signal(cx, "Hello?".to_string());
|
||||
let (counter, set_counter) = create_signal(cx, 0);
|
||||
|
||||
|
||||
// Test to make sure hydration isn't broken by
|
||||
// something like this
|
||||
let _ = [div(cx)].into_view(cx);
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use actix_files::Files;
|
||||
use actix_web::{web, App, HttpResponse, HttpServer};
|
||||
use actix_web::*;
|
||||
use hydration_test::*;
|
||||
use leptos::*;
|
||||
use futures::StreamExt;
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
|
@ -9,31 +10,30 @@ async fn main() -> std::io::Result<()> {
|
|||
.service(Files::new("/pkg", "./pkg"))
|
||||
.route("/", web::get().to(
|
||||
|| async {
|
||||
HttpResponse::Ok()
|
||||
.content_type("text/html")
|
||||
.body({
|
||||
let html = render_to_string(|cx|
|
||||
view! {
|
||||
cx,
|
||||
<App/>
|
||||
}
|
||||
);
|
||||
let html = format!(
|
||||
r#"<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script type="module">import init from '/pkg/hydration_test.js'; init();</script>
|
||||
</head>
|
||||
<body>{html}</body>
|
||||
</html>"#
|
||||
);
|
||||
let pkg_path = "/pkg/hydration_test";
|
||||
|
||||
println!("{html}");
|
||||
|
||||
html
|
||||
})
|
||||
}
|
||||
)
|
||||
let head = format!(
|
||||
r#"<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<link rel="modulepreload" href="{pkg_path}.js">
|
||||
<link rel="preload" href="{pkg_path}_bg.wasm" as="fetch" type="application/wasm" crossorigin="">
|
||||
<script type="module">import init, {{ start }} from '{pkg_path}.js'; init('{pkg_path}_bg.wasm').then(start);</script>
|
||||
"#
|
||||
);
|
||||
|
||||
let tail = "</body></html>";
|
||||
|
||||
HttpResponse::Ok().content_type("text/html").streaming(
|
||||
futures::stream::once(async move { head.clone() })
|
||||
.chain(render_to_stream(
|
||||
|cx| view! { cx, <App/> }.into_view(cx),
|
||||
))
|
||||
.chain(futures::stream::once(async { tail.to_string() }))
|
||||
.map(|html| Ok(web::Bytes::from(html)) as Result<web::Bytes>),
|
||||
)})
|
||||
))
|
||||
.bind(("127.0.0.1", 8080))?
|
||||
.run()
|
||||
|
|
Loading…
Reference in a new issue