Properties are often shortened as "Props".
Properties
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.
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 Properties;
Use in function components#
The attribute #[component] allows to optionally receive Props in the function arguments. To supply them, they are assigned via attributes in the html! macro.
- With Props
- No Props
use ;
// Then supply the prop
use ;
// No props to supply
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.
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]
- #[prop_or(value)]
- #[prop_or_else(function)]
Initialize the prop value with the default value of the field's type using the Default trait.
use ;
// Then use like this with default
// Or no override the default
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)]. The expression is evaluated when the properties are constructed and no explicit value has been given.
use *;
// Then use like this with default
// Or no override the default
Call function to initialize the prop value. function should have the signature FnMut() -> T where T is the field type. The function is called when no explicit value has been given for that attribute.
use *;
// Then use like this with default
// Or no override the default
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.
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 *;
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 *;
use autoprops;
// the #[autoprops] macro must appear BEFORE #[component], the order matters
]
message: &AttrValue,
name: &AttrValue,
)
// 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:
let mut g = 1..=3;
let props = props!;
assert_eq!;
assert_eq!;
assert_eq!;
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:
Using
Stringtype instead ofAttrValue.Why is this bad?
Stringcan be expensive to clone. Cloning is often needed when the prop value is used with hooks and callbacks.AttrValueis either a reference-counted string (Rc<str>) or a&'static str, thus very cheap to clone.Note:
AttrValueinternally isIStringfrom implicit-clone See that crate to learn more.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.Using
Vec<T>type instead ofIArray<T>.Why is this bad?
Vec<T>, just likeString, can also be expensive to clone.IArray<T>is either a reference-counted slice (Rc<[T]>) or a&'static [T], thus very cheap to clone.Note:
IArraycan be imported from implicit-clone See that crate to learn more.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.