From 05fc4cc819e2a7d29825dee79f5f61a769fa2021 Mon Sep 17 00:00:00 2001 From: Muhammad Hamza Date: Mon, 14 Aug 2023 17:09:38 +0500 Subject: [PATCH] Suspense example with struct component (#3375) * Add example for struct component context consumer * Replace untested docs example with one from examples dir Fixes #3351 --- examples/suspense/index.scss | 10 +++- examples/suspense/src/main.rs | 29 +++++++--- examples/suspense/src/struct_consumer.rs | 70 ++++++++++++++++++++++++ website/docs/concepts/suspense.mdx | 42 ++------------ 4 files changed, 102 insertions(+), 49 deletions(-) create mode 100644 examples/suspense/src/struct_consumer.rs diff --git a/examples/suspense/index.scss b/examples/suspense/index.scss index 5e3a5385e6a..22bc367b1de 100644 --- a/examples/suspense/index.scss +++ b/examples/suspense/index.scss @@ -10,10 +10,10 @@ html, body { .layout { height: 100vh; width: 100%; - display: flex; - flex-direction: column; - justify-content: center; + display: grid; + justify-items: center; align-items: center; + grid-template-columns: 1fr 1fr; } .content { @@ -69,3 +69,7 @@ button { color: rgb(100, 100, 100); } + +h2 { + text-align: center; +} diff --git a/examples/suspense/src/main.rs b/examples/suspense/src/main.rs index a51d99266f2..09b8d5e24f6 100644 --- a/examples/suspense/src/main.rs +++ b/examples/suspense/src/main.rs @@ -1,13 +1,19 @@ use web_sys::HtmlTextAreaElement; use yew::prelude::*; +mod struct_consumer; mod use_sleep; -use use_sleep::use_sleep; +pub use use_sleep::use_sleep; + +#[derive(Debug, PartialEq, Properties)] +struct PleaseWaitProps { + from: &'static str, +} #[function_component(PleaseWait)] -fn please_wait() -> Html { - html! {
{"Please wait 5 Seconds..."}
} +fn please_wait(props: &PleaseWaitProps) -> Html { + html! {
{"Please wait 5 Seconds for "}{props.from}{" component to load..."}
} } #[function_component(AppContent)] @@ -20,7 +26,7 @@ fn app_content() -> HtmlResult { let value = value.clone(); Callback::from(move |e: InputEvent| { - let input: HtmlTextAreaElement = e.target_unchecked_into(); + let input: HtmlTextAreaElement = e.target_unchecked_into::(); value.set(input.value()); }) @@ -41,14 +47,21 @@ fn app_content() -> HtmlResult { #[function_component(App)] fn app() -> Html { - let fallback = html! {}; + let fallback_fn = html! {}; + let fallback_struct = html! {}; html! {
-

{"Yew Suspense Demo"}

- - +

{" Yew Suspense Demo -- function component consumer"}

+ + + +
+
+

{"Yew Suspense Demo -- struct component consumer"}

+ +
diff --git a/examples/suspense/src/struct_consumer.rs b/examples/suspense/src/struct_consumer.rs new file mode 100644 index 00000000000..3bda239320d --- /dev/null +++ b/examples/suspense/src/struct_consumer.rs @@ -0,0 +1,70 @@ +use web_sys::HtmlTextAreaElement; +use yew::prelude::*; + +use crate::use_sleep; + +#[function_component] +pub fn WithSleep() -> HtmlResult +where + Comp: BaseComponent, +{ + let sleep = use_sleep()?; + let sleep = Callback::from(move |_| sleep()); + Ok(yew::virtual_dom::VChild::::new(AppContentProps { resleep: sleep }, None).into()) +} + +#[derive(Debug, PartialEq, Properties)] +pub struct AppContentProps { + pub resleep: Callback<()>, +} + +pub type AppContent = WithSleep; + +pub enum Msg { + ValueUpdate(String), + TakeABreak, +} + +pub struct BaseAppContent { + value: String, +} + +impl Component for BaseAppContent { + type Message = Msg; + type Properties = AppContentProps; + + fn create(_ctx: &Context) -> Self { + Self { + value: "I am writing a long story...".to_string(), + } + } + + fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { + match msg { + Msg::ValueUpdate(v) => { + self.value = v; + } + Msg::TakeABreak => { + ctx.props().resleep.emit(()); + } + }; + true + } + + fn view(&self, ctx: &Context) -> Html { + let oninput = ctx.link().callback(|e: InputEvent| { + let input: HtmlTextAreaElement = e.target_unchecked_into::(); + Msg::ValueUpdate(input.value()) + }); + let on_take_a_break = ctx.link().callback(|_| Msg::TakeABreak); + html! { +
+ +
+ +
{"You can take a break at anytime"}
{"and your work will be preserved."}
+
+
+ } + } +} diff --git a/website/docs/concepts/suspense.mdx b/website/docs/concepts/suspense.mdx index 74d6dff1ddd..6c697d82f00 100644 --- a/website/docs/concepts/suspense.mdx +++ b/website/docs/concepts/suspense.mdx @@ -136,45 +136,11 @@ fn app() -> Html { ### Use Suspense in Struct Components It's not possible to suspend a struct component directly. However, you -can use a function component as a [HOC](../advanced-topics/struct-components/hoc) to -achieve suspense-based data fetching. +can use a function component as a [Higher Order Component](../advanced-topics/struct-components/hoc) +to achieve suspense-based data fetching. -```rust ,ignore -use yew::prelude::*; - -#[function_component(WithUser)] -fn with_user() -> HtmlResult -where T: BaseComponent -{ - let user = use_user()?; - - Ok(html! {}) -} - -#[derive(Debug, PartialEq, Properties)] -pub struct UserContentProps { - pub user: User, -} - -pub struct BaseUserContent; - -impl Component for BaseUserContent { - type Properties = UserContentProps; - type Message = (); - - fn create(ctx: &Context) -> Self { - Self - } - - fn view(&self, ctx: &Context) -> Html { - let name = ctx.props().user.name; - - html! {
{"Hello, "}{name}{"!"}
} - } -} - -pub type UserContent = WithUser; -``` +The [suspense example in the Yew repository](https://github.com/yewstack/yew/tree/master/examples/suspense/src/struct_consumer.rs) +demonstrates how to use. ## Relevant examples