Skip to main content
Version: Next

Properties

note

Properties are often shortened as "Props".

Properties are essentially component arguments that Yew can keep watch on.

A type has to implement the Properties trait before it can be used as the properties of a component.

Reactivity

Yew checks if props have changed when reconciling the Virtual DOM during re-rendering, to know if nested components need to be re-rendered. This way Yew can be considered a very reactive framework, as changes from the parent will always be propagated downward, and the view will never be out of sync with the data coming from props/state.

tip

If you have not yet completed the tutorial, try it out and test this reactivity yourself!

Derive macro

Yew provides a derive macro to easily implement the Properties trait on structs.

Types for which you derive Properties must also implement PartialEq so Yew can do data comparison.

use yew::Properties;

#[derive(Properties, PartialEq)]
pub struct Props {
pub is_loading: bool,
}

Use in function components

The attribute #[function_component] allows to optionally receive Props in the function arguments. To supply them, they are assigned via attributes in the html! macro.

use yew::{function_component, html, Html, Properties};

#[derive(Properties, PartialEq)]
pub struct Props {
pub is_loading: bool,
}

#[function_component]
fn HelloWorld(&Props { is_loading }: &Props) -> Html {
html! { <>{"Am I loading? - "}{is_loading}</> }
}

// Then supply the prop
#[function_component]
fn App() -> Html {
html! { <HelloWorld is_loading=true /> }
}

Derive macro field attributes

When deriving Properties all fields are required by default. The following attributes allow you to give your props default values which will be used when the parent has not set them.

tip

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.

Initialize the prop value with the default value of the field's type using the Default trait.

use yew::{function_component, html, Html, Properties};

#[derive(Properties, PartialEq)]
pub struct Props {
#[prop_or_default]
pub is_loading: bool,
}

#[function_component]
fn HelloWorld(&Props { is_loading }: &Props) -> Html {
if is_loading {
html! { "Loading" }
} else {
html! { "Hello world" }
}
}

// Then use like this with default
#[function_component]
fn Case1() -> Html {
html! { <HelloWorld /> }
}
// Or no override the default
#[function_component]
fn Case2() -> Html {
html! { <HelloWorld is_loading=true /> }
}

Memory/speed overhead of using Properties

Internally properties are reference counted. This means that only a shared 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.

tip

Make use of AttrValue which is our custom type for attribute values instead of defining them as String or another similar type.

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 can't 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::prelude::*;

#[derive(Properties, PartialEq)]
pub struct Props {
#[prop_or_default]
pub is_loading: bool,
#[prop_or(AttrValue::Static("Bob"))]
pub name: AttrValue,
}

#[function_component]
fn Hello(&Props { is_loading, ref name }: &Props) -> Html {
if is_loading {
html! { "Loading" }
} else {
html! { <>{"Hello "}{name}</> }
}
}

#[function_component]
fn App() -> Html {
let pre_made_props = yew::props! {
Props {} // Notice we did not need to specify name prop
};
html! { <Hello ..pre_made_props /> }
}

Automatically generate properties (yew-autoprops)

In order to streamline your development process, you can also use the macro #[autoprops] (from the crate yew-autoprops) that will automatically generate the Properties struct for you.

use yew::prelude::*;
use yew_autoprops::autoprops;

// the #[autoprops] macro must appear BEFORE #[function_component], the order matters
#[autoprops]
#[function_component]
fn Greetings(
#[prop_or_default]
is_loading: bool,
#[prop_or(AttrValue::Static("Hello"))]
message: &AttrValue,
#[prop_or(AttrValue::Static("World"))]
name: &AttrValue,
) -> Html {
if is_loading {
html! { "Loading" }
} else {
html! { <>{message}{" "}{name}</> }
}
}

// The properties struct "GreetingsProps" will be generated automatically.
//
// `is_loading` will be passed as value to the components while `message` and
// `name` will use references because of the leading `&` in the definition.

Evaluation Order

Props are evaluated in the order they're specified, as shown by the following example:

#[derive(yew::Properties, PartialEq)]
struct Props { first: usize, second: usize, last: usize }

fn main() {
let mut g = 1..=3;
let props = yew::props!(Props { first: g.next().unwrap(), second: g.next().unwrap(), last: g.next().unwrap() });

assert_eq!(props.first, 1);
assert_eq!(props.second, 2);
assert_eq!(props.last, 3);
}

Anti Patterns

While almost any Rust type can be passed as properties, there are some anti-patterns that should be avoided. These include, but are not limited to:

  1. Using String type instead of AttrValue.
    Why is this bad? String can be expensive to clone. Cloning is often needed when the prop value is used with hooks and callbacks. AttrValue is either a reference-counted string (Rc<str>) or a &'static str, thus very cheap to clone.
    Note: AttrValue internally is IString from implicit-clone See that crate to learn more.
  2. Using interior mutability.
    Why is this bad? Interior mutability (such as with RefCell, Mutex, etc.) should generally be avoided. It can cause problems with re-renders (Yew doesn't know when the state has changed) so you may have to manually force a render. Like all things, it has its place. Use it with caution.
  3. Using Vec type instead of IArray.
    Why is this bad? Vec, just like String, can also be expensive to clone. IArray is either a reference-counted slice (Rc<T>) or a &'static [T], thus very cheap to clone.
    Note: IArray can be imported from implicit-clone See that crate to learn more.
  4. You tell us. Did you run into an edge-case you wish you knew about earlier? Feel free to create an issue or PR a fix to this documentation.

yew-autoprops

yew-autoprops is an experimental package that allows one to create the Props struct on the fly out of the arguments of your function. Might be useful, if the properties struct is never reused.