From 69b27382f2638ae7e413b22b75ef3beab897f3a5 Mon Sep 17 00:00:00 2001 From: Richard LASJUNIES Date: Fri, 8 May 2020 18:47:25 +0200 Subject: [PATCH 1/3] properties page, previous speed trick at the end --- src/concepts/components/properties.md | 550 +++++++++++++++++++++++++- 1 file changed, 537 insertions(+), 13 deletions(-) diff --git a/src/concepts/components/properties.md b/src/concepts/components/properties.md index ba41a8c..f74a5f6 100644 --- a/src/concepts/components/properties.md +++ b/src/concepts/components/properties.md @@ -1,26 +1,551 @@ --- -description: Parent to child communication +description: The component could expose property attributes to receive data from the parent html component --- # Properties -Properties enable child and parent components to communicate with each other. +It is a common need to receive data from the parent component using properties. -## Derive macro +The properties are defined in a dedicated Rust struct derivating `Properties` and `Clone`traits. -Don't try to implement `Properties` yourself, derive it by using `#[derive(Properties)]` instead. +> This struct is usually named `Props` -{% hint style="info" %} -Types for which you derive `Properties` must also implement `Clone`. This can be done by either using `#[derive(Properties, Clone)` or manually implementing `Clone` for your type. -{% endhint %} +The properties bag is attached to the state adding the field `props` in the component struct and defining the `Properties` `Type` in the component trait implementation. -### Required attributes +The properties have to be intialized in the `create` method. As for `link`, the framework push to the method the bag of the properties and can be used to attach it to the internal state. -The fields within a struct that derives `Properties` are required by default. When a field is missing and the component is created in the `html!` macro, a compiler error is returned. For fields with optional properties, use the `#[prop_or_default]` attribute to use the default value for that type when the prop is not specified. To specify a value, use the `#[prop_or_else(value)]` attribute where value is the default value for the property. For example, to default a boolean value as `true`, use the attribute `#[prop_or_else(true)]`. It is common for optional properties to use the `Option` enum which has the default value `None`. +It' possible to define some attributes to the properties as: -### PartialEq +- optional and initialized with Rust default value +- optional and initialieed with component default value +- mandatory, the parent must define a value for the attribute -It is likely to make sense to derive `PartialEq` on your props if you can do this. Using `PartialEq` makes it much easier to avoid unnecessary rerendering \(this is explained in the **Optimizations & Best Practices** section\). +> remark: for convenience and/or performance optimization `Props` can derive `PartialEq` to avoid to re-render if there is no changed.cf. `change` method + +```rust +use yew::prelude::*; + +pub struct UseOfPropertyComponent { + link: ComponentLink, + props: Props, + name: String, + show_message: bool, +} + +pub enum Msg { + Click(), +} + +#[derive(Properties, Clone, PartialEq)] +pub struct Props{ + pub name: String, +} + +impl Component for UseOfPropertyComponent { + type Message = Msg; + type Properties = Props; + + fn create(props: Self::Properties, link: ComponentLink) -> Self { + Self { + link, + props: props.clone(), + name: props.name.into(), + show_message: false, + } + } + + fn update(&mut self, msg: Self::Message) -> ShouldRender { + match msg { + Msg::Click() => self.show_message = true, + } + true + } + + fn change(&mut self, props: Self::Properties) -> ShouldRender { + if self.props != props { + self.props = props; + true + } else { + false + } + } + + fn view(&self) -> Html { + if !self.show_message { + html! { + <> + + + } + } else { + html! { + <> +

{format!("Hello {}",self.name)}

+ + } + } + } +} + +``` + +In order to use this component you have to: + +```html +// ... +
+ {"In this example we pass the name as parameter of the Yew component."} + +
+// ... + +``` + +## Define the properties structure + +```rust +# use yew::prelude::*; +# +# pub struct UseOfPropertyComponent { +# link: ComponentLink, +# props: Props, +# name: String, +# show_message: bool, +# } +# +# pub enum Msg { +# Click(), +# } + +// ... +#[derive(Properties, Clone, PartialEq)] +pub struct Props{ + pub name: String, +} +// ... + +# impl Component for UseOfPropertyComponent { +# type Message = Msg; +# type Properties = Props; +# +# fn create(props: Self::Properties, link: ComponentLink) -> Self { +# Self { +# link, +# props: props.clone(), +# name: props.name.into(), +# show_message: false, +# } +# } +# +# fn update(&mut self, msg: Self::Message) -> ShouldRender { +# match msg { +# Msg::Click() => self.show_message = true, +# } +# true +# } +# +# fn change(&mut self, props: Self::Properties) -> ShouldRender { +# if self.props != props { +# self.props = props; +# true +# } else { +# false +# } +# } +# +# fn view(&self) -> Html { +# if !self.show_message { +# html! { +# <> +# +# +# } +# } else { +# html! { +# <> +#

{format!("Hello {}",self.name)}

+# +# } +# } +# } +# } + +``` + +## Attach the property bag in the state + +```rust +# use yew::prelude::*; +// ... +pub struct UseOfPropertyComponent { + link: ComponentLink, + props: Props, + name: String, + show_message: bool, +} +// ... +# +# pub enum Msg { +# Click(), +# } +# +# #[derive(Properties, Clone, PartialEq)] +# pub struct Props{ +# pub name: String, +# } +# +# impl Component for UseOfPropertyComponent { +# type Message = Msg; +# type Properties = Props; +# +# fn create(props: Self::Properties, link: ComponentLink) -> Self { +# Self { +# link, +# props: props.clone(), +# name: props.name.into(), +# show_message: false, +# } +# } +# +# fn update(&mut self, msg: Self::Message) -> ShouldRender { +# match msg { +# Msg::Click() => self.show_message = true, +# } +# true +# } +# +# fn change(&mut self, props: Self::Properties) -> ShouldRender { +# if self.props != props { +# self.props = props; +# true +# } else { +# false +# } +# } +# +# fn view(&self) -> Html { +# if !self.show_message { +# html! { +# <> +# +# +# } +# } else { +# html! { +# <> +#

{format!("Hello {}",self.name)}

+# +# } +# } +# } +# } + +``` + +## Initialize the properties + +```rust +# use yew::prelude::*; +# +# pub struct UseOfPropertyComponent { +# link: ComponentLink, +# props: Props, +# name: String, +# show_message: bool, +# } +# +# pub enum Msg { +# Click(), +# } +# +# #[derive(Properties, Clone, PartialEq)] +# pub struct Props{ +# pub name: String, +# } +# +# impl Component for UseOfPropertyComponent { +# type Message = Msg; +# type Properties = Props; +// ... + fn create(props: Self::Properties, link: ComponentLink) -> Self { + Self { + link, + props: props.clone(), + name: props.name.into(), + show_message: false, + } + } +// ... +# fn update(&mut self, msg: Self::Message) -> ShouldRender { +# match msg { +# Msg::Click() => self.show_message = true, +# } +# true +# } +# +# +# fn change(&mut self, props: Self::Properties) -> ShouldRender { +# if self.props != props { +# self.props = props; +# true +# } else { +# false +# } +# } +# +# fn view(&self) -> Html { +# if !self.show_message { +# html! { +# <> +# +# +# } +# } else { +# html! { +# <> +#

{format!("Hello {}",self.name)}

+# +# } +# } +# } +# } + +``` + +> Here, to simply extend the previous example, we `.clone()` the `props` argument. It may not be needed in your code + +## Mandatory property + +In this example the property have to be defined using the component. If it's omitted a compilatioin error is raised. The error looks like: + +> no method named `build` found for struct `components::comp4::PropsBuilder<...PropsBuilderStep_missing_required_prop_name>` in the current scope +> method not found in `...::PropsBuilder<...PropsBuilderStep_missing_required_prop_name>`rustc(E0599) +comp4.rs(14, 10): method `build` not found for this` + +## Optional property + +Property can be defined optional just adding `#[prop_or_default]` on the property. In that case the property value will be initialized by the default Rust type value. + +```rust +# use yew::prelude::*; +# +# pub struct UseOfPropertyComponent { +# link: ComponentLink, +# props: Props, +# name: String, +# show_message: bool, +# } +# +# pub enum Msg { +# Click(), +# } + +// ... +#[derive(Properties, Clone, PartialEq)] +pub struct Props{ + #[prop_or_default] + pub name: String, +} +// ... + +# impl Component for UseOfPropertyComponent { +# type Message = Msg; +# type Properties = Props; +# +# fn create(props: Self::Properties, link: ComponentLink) -> Self { +# Self { +# link, +# props: props.clone(), +# name: props.name.into(), +# show_message: false, +# } +# } +# +# fn update(&mut self, msg: Self::Message) -> ShouldRender { +# match msg { +# Msg::Click() => self.show_message = true, +# } +# true +# } +# +# fn change(&mut self, props: Self::Properties) -> ShouldRender { +# if self.props != props { +# self.props = props; +# true +# } else { +# false +# } +# } +# +# fn view(&self) -> Html { +# if !self.show_message { +# html! { +# <> +# +# +# } +# } else { +# html! { +# <> +#

{format!("Hello {}",self.name)}

+# +# } +# } +# } +# } + + + +``` + +In that case we will just say "Hello" ;-) + +## Optional property with component default value + +Property can be defined optional but adding a default component value adding `#[prop_or_(your_default_value)]` on the property. + +```rust +# use yew::prelude::*; +# +# pub struct UseOfPropertyComponent { +# link: ComponentLink, +# props: Props, +# name: String, +# show_message: bool, +# } +# +# pub enum Msg { +# Click(), +# } +# +// ... +#[derive(Properties, Clone, PartialEq)] +pub struct Props{ + #[prop_or("Clark by default".to_string())] + pub name: String, +} +// ... +# +# impl Component for UseOfPropertyComponent { +# type Message = Msg; +# type Properties = Props; +# +# fn create(props: Self::Properties, link: ComponentLink) -> Self { +# Self { +# link, +# props: props.clone(), +# name: props.name.into(), +# show_message: false, +# } +# } +# +# fn update(&mut self, msg: Self::Message) -> ShouldRender { +# match msg { +# Msg::Click() => self.show_message = true, +# } +# true +# } +# +# fn change(&mut self, props: Self::Properties) -> ShouldRender { +# if self.props != props { +# self.props = props; +# true +# } else { +# false +# } +# } +# +# fn view(&self) -> Html { +# if !self.show_message { +# html! { +# <> +# +# +# } +# } else { +# html! { +# <> +#

{format!("Hello {}",self.name)}

+# +# } +# } +# } +# } +``` + +In that case we will say "Hello Clark by default" ;-) + +## Optimize rendering in the `change` method + +In order to avoid unecessary rendring it's possible to compare the mutation of the `props` bag in the `change` method. +This optimization imply to derive `PartialEq` for the `Props` struct to easily compare the `props` bag passed as argument of the method and the one in the internal state of the component. + +```rust +# use yew::prelude::*; +# +# pub struct UseOfPropertyComponent { +# link: ComponentLink, +# props: Props, +# name: String, +# show_message: bool, +# } +# +# pub enum Msg { +# Click(), +# } +# +# #[derive(Properties, Clone, PartialEq)] +# pub struct Props{ +# pub name: String, +# } +# +# impl Component for UseOfPropertyComponent { +# type Message = Msg; +# type Properties = Props; +# +# fn create(props: Self::Properties, link: ComponentLink) -> Self { +# Self { +# link, +# props: props.clone(), +# name: props.name.into(), +# show_message: false, +# } +# } +# +# fn update(&mut self, msg: Self::Message) -> ShouldRender { +# match msg { +# Msg::Click() => self.show_message = true, +# } +# true +# } +// ... + fn change(&mut self, props: Self::Properties) -> ShouldRender { + if self.props != props { + self.props = props; + true + } else { + false + } + } +// ... + +# fn view(&self) -> Html { +# if !self.show_message { +# html! { +# <> +# +# +# } +# } else { +# html! { +# <> +#

{format!("Hello {}",self.name)}

+# +# } +# } +# } +# } +``` ## Memory/speed overhead of using Properties @@ -32,7 +557,7 @@ The implication of this is if you would otherwise be passing _huge_ amounts of d If you won't need to modify the data passed down through props you can wrap it in an `Rc` so that only a reference-counted pointer to the data is cloned, instead of the actual data itself. -## Example +### Example ```rust use std::rc::Rc; @@ -72,4 +597,3 @@ pub struct LinkProps { active: bool, } ``` - From 5fb93fd4255e2857490f028a231beb66f9bd1571 Mon Sep 17 00:00:00 2001 From: Richard LASJUNIES Date: Sun, 10 May 2020 10:02:19 +0200 Subject: [PATCH 2/3] update based on Teymour feed-backs #1 --- src/concepts/components/properties.md | 51 +++++++++++++-------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/src/concepts/components/properties.md b/src/concepts/components/properties.md index f74a5f6..8c3f955 100644 --- a/src/concepts/components/properties.md +++ b/src/concepts/components/properties.md @@ -4,24 +4,20 @@ description: The component could expose property attributes to receive data from # Properties -It is a common need to receive data from the parent component using properties. +It’s good practice to divide up your application into multiple components and split them across different files. As your application becomes larger, this quickly becomes essential. For these components to be able to communicate with each other, components have properties – these are values which parent components pass to child components. -The properties are defined in a dedicated Rust struct derivating `Properties` and `Clone`traits. +A component's properties should be defined using a separate struct which derives `Properties` and `Clone` traits. -> This struct is usually named `Props` +> The `Properties` trait requires that the `Clone` trait is implemented for all types for which `Properties` is derived. -The properties bag is attached to the state adding the field `props` in the component struct and defining the `Properties` `Type` in the component trait implementation. +> It is common for this struct to be named `Props` -The properties have to be intialized in the `create` method. As for `link`, the framework push to the method the bag of the properties and can be used to attach it to the internal state. - -It' possible to define some attributes to the properties as: +Properties may be defined as: - optional and initialized with Rust default value -- optional and initialieed with component default value +- optional and initialized with component default value - mandatory, the parent must define a value for the attribute -> remark: for convenience and/or performance optimization `Props` can derive `PartialEq` to avoid to re-render if there is no changed.cf. `change` method - ```rust use yew::prelude::*; @@ -101,7 +97,7 @@ In order to use this component you have to: ``` -## Define the properties structure +## Defining the properties struct ```rust # use yew::prelude::*; @@ -172,7 +168,7 @@ pub struct Props{ ``` -## Attach the property bag in the state +## Attaching the properties to the state ```rust # use yew::prelude::*; @@ -242,7 +238,7 @@ pub struct UseOfPropertyComponent { ``` -## Initialize the properties +## Initializing the properties ```rust # use yew::prelude::*; @@ -312,17 +308,11 @@ pub struct UseOfPropertyComponent { ``` -> Here, to simply extend the previous example, we `.clone()` the `props` argument. It may not be needed in your code - -## Mandatory property - -In this example the property have to be defined using the component. If it's omitted a compilatioin error is raised. The error looks like: +> Here, to simply extend the previous example, we clone the value of the `props` argument. It may not be needed in your code -> no method named `build` found for struct `components::comp4::PropsBuilder<...PropsBuilderStep_missing_required_prop_name>` in the current scope -> method not found in `...::PropsBuilder<...PropsBuilderStep_missing_required_prop_name>`rustc(E0599) -comp4.rs(14, 10): method `build` not found for this` +## Defining property attributes -## Optional property +### Optional property Property can be defined optional just adding `#[prop_or_default]` on the property. In that case the property value will be initialized by the default Rust type value. @@ -400,9 +390,9 @@ pub struct Props{ In that case we will just say "Hello" ;-) -## Optional property with component default value +### Optional property with component default value -Property can be defined optional but adding a default component value adding `#[prop_or_(your_default_value)]` on the property. +A property can be defined as an optional property. In this case, it becomes necessary to define a default component value. Yew will automatically use this value if it is not provided when the component is initialized. Such properties should be annotated with the #[prop_or_(default_value)] attribute where default_value specifies the value which Yew should use. ```rust # use yew::prelude::*; @@ -475,9 +465,18 @@ pub struct Props{ In that case we will say "Hello Clark by default" ;-) -## Optimize rendering in the `change` method +### Mandatory property + +If no attribute is defined the property will be "mandatory". So, if the property is omitted a compilation error is raised. The error looks like: + +> no method named `build` found for struct `components::comp4::PropsBuilder<...PropsBuilderStep_missing_required_prop_name>` in the current scope +> method not found in `...::PropsBuilder<...PropsBuilderStep_missing_required_prop_name>`rustc(E0599) +comp4.rs(14, 10): method `build` not found for this` + + +## Optimizing rendering in the `change` method -In order to avoid unecessary rendring it's possible to compare the mutation of the `props` bag in the `change` method. +In order to avoid unecessary rendering it's possible to compare the mutation of the `props` bag in the `change` method. This optimization imply to derive `PartialEq` for the `Props` struct to easily compare the `props` bag passed as argument of the method and the one in the internal state of the component. ```rust From ed58107839d5ca17ed27983a256dc74913cd9fde Mon Sep 17 00:00:00 2001 From: Richard LASJUNIES Date: Sun, 10 May 2020 18:20:24 +0200 Subject: [PATCH 3/3] fix from other pages, del tests for readabilility --- src/concepts/components/properties.md | 357 +------------------------- 1 file changed, 4 insertions(+), 353 deletions(-) diff --git a/src/concepts/components/properties.md b/src/concepts/components/properties.md index 8c3f955..156cef2 100644 --- a/src/concepts/components/properties.md +++ b/src/concepts/components/properties.md @@ -29,7 +29,7 @@ pub struct UseOfPropertyComponent { } pub enum Msg { - Click(), + Click, } #[derive(Properties, Clone, PartialEq)] @@ -52,7 +52,7 @@ impl Component for UseOfPropertyComponent { fn update(&mut self, msg: Self::Message) -> ShouldRender { match msg { - Msg::Click() => self.show_message = true, + Msg::Click => self.show_message = true, } true } @@ -69,15 +69,11 @@ impl Component for UseOfPropertyComponent { fn view(&self) -> Html { if !self.show_message { html! { - <> - - + } } else { html! { - <> -

{format!("Hello {}",self.name)}

- +

{format!("Hello {}",self.name)}

} } } @@ -100,19 +96,6 @@ In order to use this component you have to: ## Defining the properties struct ```rust -# use yew::prelude::*; -# -# pub struct UseOfPropertyComponent { -# link: ComponentLink, -# props: Props, -# name: String, -# show_message: bool, -# } -# -# pub enum Msg { -# Click(), -# } - // ... #[derive(Properties, Clone, PartialEq)] pub struct Props{ @@ -120,58 +103,11 @@ pub struct Props{ } // ... -# impl Component for UseOfPropertyComponent { -# type Message = Msg; -# type Properties = Props; -# -# fn create(props: Self::Properties, link: ComponentLink) -> Self { -# Self { -# link, -# props: props.clone(), -# name: props.name.into(), -# show_message: false, -# } -# } -# -# fn update(&mut self, msg: Self::Message) -> ShouldRender { -# match msg { -# Msg::Click() => self.show_message = true, -# } -# true -# } -# -# fn change(&mut self, props: Self::Properties) -> ShouldRender { -# if self.props != props { -# self.props = props; -# true -# } else { -# false -# } -# } -# -# fn view(&self) -> Html { -# if !self.show_message { -# html! { -# <> -# -# -# } -# } else { -# html! { -# <> -#

{format!("Hello {}",self.name)}

-# -# } -# } -# } -# } - ``` ## Attaching the properties to the state ```rust -# use yew::prelude::*; // ... pub struct UseOfPropertyComponent { link: ComponentLink, @@ -180,88 +116,11 @@ pub struct UseOfPropertyComponent { show_message: bool, } // ... -# -# pub enum Msg { -# Click(), -# } -# -# #[derive(Properties, Clone, PartialEq)] -# pub struct Props{ -# pub name: String, -# } -# -# impl Component for UseOfPropertyComponent { -# type Message = Msg; -# type Properties = Props; -# -# fn create(props: Self::Properties, link: ComponentLink) -> Self { -# Self { -# link, -# props: props.clone(), -# name: props.name.into(), -# show_message: false, -# } -# } -# -# fn update(&mut self, msg: Self::Message) -> ShouldRender { -# match msg { -# Msg::Click() => self.show_message = true, -# } -# true -# } -# -# fn change(&mut self, props: Self::Properties) -> ShouldRender { -# if self.props != props { -# self.props = props; -# true -# } else { -# false -# } -# } -# -# fn view(&self) -> Html { -# if !self.show_message { -# html! { -# <> -# -# -# } -# } else { -# html! { -# <> -#

{format!("Hello {}",self.name)}

-# -# } -# } -# } -# } - ``` ## Initializing the properties ```rust -# use yew::prelude::*; -# -# pub struct UseOfPropertyComponent { -# link: ComponentLink, -# props: Props, -# name: String, -# show_message: bool, -# } -# -# pub enum Msg { -# Click(), -# } -# -# #[derive(Properties, Clone, PartialEq)] -# pub struct Props{ -# pub name: String, -# } -# -# impl Component for UseOfPropertyComponent { -# type Message = Msg; -# type Properties = Props; // ... fn create(props: Self::Properties, link: ComponentLink) -> Self { Self { @@ -272,40 +131,6 @@ pub struct UseOfPropertyComponent { } } // ... -# fn update(&mut self, msg: Self::Message) -> ShouldRender { -# match msg { -# Msg::Click() => self.show_message = true, -# } -# true -# } -# -# -# fn change(&mut self, props: Self::Properties) -> ShouldRender { -# if self.props != props { -# self.props = props; -# true -# } else { -# false -# } -# } -# -# fn view(&self) -> Html { -# if !self.show_message { -# html! { -# <> -# -# -# } -# } else { -# html! { -# <> -#

{format!("Hello {}",self.name)}

-# -# } -# } -# } -# } - ``` > Here, to simply extend the previous example, we clone the value of the `props` argument. It may not be needed in your code @@ -317,19 +142,6 @@ pub struct UseOfPropertyComponent { Property can be defined optional just adding `#[prop_or_default]` on the property. In that case the property value will be initialized by the default Rust type value. ```rust -# use yew::prelude::*; -# -# pub struct UseOfPropertyComponent { -# link: ComponentLink, -# props: Props, -# name: String, -# show_message: bool, -# } -# -# pub enum Msg { -# Click(), -# } - // ... #[derive(Properties, Clone, PartialEq)] pub struct Props{ @@ -338,54 +150,6 @@ pub struct Props{ } // ... -# impl Component for UseOfPropertyComponent { -# type Message = Msg; -# type Properties = Props; -# -# fn create(props: Self::Properties, link: ComponentLink) -> Self { -# Self { -# link, -# props: props.clone(), -# name: props.name.into(), -# show_message: false, -# } -# } -# -# fn update(&mut self, msg: Self::Message) -> ShouldRender { -# match msg { -# Msg::Click() => self.show_message = true, -# } -# true -# } -# -# fn change(&mut self, props: Self::Properties) -> ShouldRender { -# if self.props != props { -# self.props = props; -# true -# } else { -# false -# } -# } -# -# fn view(&self) -> Html { -# if !self.show_message { -# html! { -# <> -# -# -# } -# } else { -# html! { -# <> -#

{format!("Hello {}",self.name)}

-# -# } -# } -# } -# } - - - ``` In that case we will just say "Hello" ;-) @@ -395,19 +159,6 @@ In that case we will just say "Hello" ;-) A property can be defined as an optional property. In this case, it becomes necessary to define a default component value. Yew will automatically use this value if it is not provided when the component is initialized. Such properties should be annotated with the #[prop_or_(default_value)] attribute where default_value specifies the value which Yew should use. ```rust -# use yew::prelude::*; -# -# pub struct UseOfPropertyComponent { -# link: ComponentLink, -# props: Props, -# name: String, -# show_message: bool, -# } -# -# pub enum Msg { -# Click(), -# } -# // ... #[derive(Properties, Clone, PartialEq)] pub struct Props{ @@ -415,52 +166,6 @@ pub struct Props{ pub name: String, } // ... -# -# impl Component for UseOfPropertyComponent { -# type Message = Msg; -# type Properties = Props; -# -# fn create(props: Self::Properties, link: ComponentLink) -> Self { -# Self { -# link, -# props: props.clone(), -# name: props.name.into(), -# show_message: false, -# } -# } -# -# fn update(&mut self, msg: Self::Message) -> ShouldRender { -# match msg { -# Msg::Click() => self.show_message = true, -# } -# true -# } -# -# fn change(&mut self, props: Self::Properties) -> ShouldRender { -# if self.props != props { -# self.props = props; -# true -# } else { -# false -# } -# } -# -# fn view(&self) -> Html { -# if !self.show_message { -# html! { -# <> -# -# -# } -# } else { -# html! { -# <> -#

{format!("Hello {}",self.name)}

-# -# } -# } -# } -# } ``` In that case we will say "Hello Clark by default" ;-) @@ -473,50 +178,12 @@ If no attribute is defined the property will be "mandatory". So, if the property > method not found in `...::PropsBuilder<...PropsBuilderStep_missing_required_prop_name>`rustc(E0599) comp4.rs(14, 10): method `build` not found for this` - ## Optimizing rendering in the `change` method In order to avoid unecessary rendering it's possible to compare the mutation of the `props` bag in the `change` method. This optimization imply to derive `PartialEq` for the `Props` struct to easily compare the `props` bag passed as argument of the method and the one in the internal state of the component. ```rust -# use yew::prelude::*; -# -# pub struct UseOfPropertyComponent { -# link: ComponentLink, -# props: Props, -# name: String, -# show_message: bool, -# } -# -# pub enum Msg { -# Click(), -# } -# -# #[derive(Properties, Clone, PartialEq)] -# pub struct Props{ -# pub name: String, -# } -# -# impl Component for UseOfPropertyComponent { -# type Message = Msg; -# type Properties = Props; -# -# fn create(props: Self::Properties, link: ComponentLink) -> Self { -# Self { -# link, -# props: props.clone(), -# name: props.name.into(), -# show_message: false, -# } -# } -# -# fn update(&mut self, msg: Self::Message) -> ShouldRender { -# match msg { -# Msg::Click() => self.show_message = true, -# } -# true -# } // ... fn change(&mut self, props: Self::Properties) -> ShouldRender { if self.props != props { @@ -528,22 +195,6 @@ This optimization imply to derive `PartialEq` for the `Props` struct to easily c } // ... -# fn view(&self) -> Html { -# if !self.show_message { -# html! { -# <> -# -# -# } -# } else { -# html! { -# <> -#

{format!("Hello {}",self.name)}

-# -# } -# } -# } -# } ``` ## Memory/speed overhead of using Properties