Properties
Properties enable child and parent components to communicate with each other.
Every component has an associated properties type which describes what is passed down from the parent.
In theory, this can be any type that implements the Properties
trait, but in practice, there is no
reason for it to be anything but a struct where each field represents a property.
Derive macro
Instead of implementing the Properties
trait yourself, you should use #[derive(Properties)]
to
automatically generate the implementation instead.
Types for which you derive Properties
must also implement PartialEq
.
Field attributes
When deriving Properties
, all fields are required by default.
The following attributes allow you to give your props initial values which will be used unless they are set to another value.
Attributes aren't visible in Rustdoc generated documentation. The doc strings of your properties should mention whether a prop is optional and if it has a special default value.
#[prop_or_default]
Initialize the prop value with the default value of the field's type using the Default
trait.
#[prop_or(value)]
Use value
to initialize the prop value. value
can be any expression that returns the field's type.
For example, to default a boolean prop to true
, use the attribute #[prop_or(true)]
.
#[prop_or_else(function)]
Call function
to initialize the prop value. function
should have the signature FnMut() -> T
where T
is the field type.
PartialEq
Properties
require PartialEq
to be implemented. This is so that they can be compared by Yew to call the changed
method
only when they change.
Memory/speed overhead of using Properties
Internally properties are reference counted. This means that only a pointer is passed down the component tree for props. It saves us from the cost of having to clone the entire props, which might be expensive.
Make use of AttrValue
which is our custom type for attribute values instead of defining them as String or another similar type.
Example
use yew::Properties;
/// Importing the AttrValue from virtual_dom
use yew::virtual_dom::AttrValue;
#[derive(Clone, PartialEq)]
pub enum LinkColor {
Blue,
Red,
Green,
Black,
Purple,
}
fn create_default_link_color() -> LinkColor {
LinkColor::Blue
}
#[derive(Properties, PartialEq)]
pub struct LinkProps {
/// The link must have a target.
href: AttrValue,
/// Also notice that we are using AttrValue instead of String
text: AttrValue,
/// Color of the link. Defaults to `Blue`.
#[prop_or_else(create_default_link_color)]
color: LinkColor,
/// The view function will not specify a size if this is None.
#[prop_or_default]
size: Option<u32>,
/// When the view function does not specify active, it defaults to true.
#[prop_or(true)]
active: bool,
}
Props macro
The yew::props!
macro allows you to build properties the same way the html!
macro does it.
The macro uses the same syntax as a struct expression except that you cannot use attributes or a base expression (Foo { ..base }
).
The type path can either point to the props directly (path::to::Props
) or the associated properties of a component (MyComp::Properties
).
use yew::{props, Properties, virtual_dom::AttrValue};
#[derive(Clone, PartialEq)]
pub enum LinkColor {
Blue,
Red,
Green,
Black,
Purple,
}
fn create_default_link_color() -> LinkColor {
LinkColor::Blue
}
#[derive(Properties, PartialEq)]
pub struct LinkProps {
/// The link must have a target.
href: AttrValue,
/// Also notice that we're using AttrValue instead of String
text: AttrValue,
/// Color of the link. Defaults to `Blue`.
#[prop_or_else(create_default_link_color)]
color: LinkColor,
/// The view function will not specify a size if this is None.
#[prop_or_default]
size: Option<u32>,
/// When the view function doesn't specify active, it defaults to true.
#[prop_or(true)]
active: bool,
}
impl LinkProps {
/// Notice that this function receives href and text as String
/// We can use `AttrValue::from` to convert it to a `AttrValue`
pub fn new_link_with_size(href: String, text: String, size: u32) -> Self {
props! {LinkProps {
href: AttrValue::from(href),
text: AttrValue::from(text),
size,
}}
}
}