Properties without #[props(required)] or #[props(default = "fn_name")] are implicitly set to their default value.
Properties should be treated as required unless indicated otherwise
#[derive(Clone, Properties)]
struct Props {
#[prop_or(3)],
countdown: usize,
#[prop_or_else(Callback::noop)]
on_click: Callback<()>,
#[prop_or(true)]
display: bool,
#[prop_or_default]
highlight: bool,
// implicitly required
required: MyRequiredValue,
#[prop_or_default]
opt_value: Option<Value>,
// implicitly required
opt_required: Option<Value>,
}
#[derive(Clone, Properties)]
struct Props {
#[props(default = "countdown_default")],
countdown: usize,
#[props(default = "Callback::noop")]
on_click: Callback<()>,
#[props(default = "display_default")]
display: bool,
// implicitly optional and will default to `false`
highlight: bool,
#[props(required)]
required: MyRequiredValue,
// implicitly optional and will default to `None`
opt_value: Option<Value>,
#[props(required)]
opt_required: Option<Value>,
}
fn countdown_default() -> usize {
3
}
fn display_default() -> bool {
true
}
Now that we have a default attribute for properties, I think it makes sense to require it for indicating when properties are optional. So this means we would drop support for #[props(required)]
You may ask, why not follow the precedent that serde set for default values? Link
Serde was designed before arbitrary token streams were allowed for helper attributes in Rust 1.34.0: https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#custom-attributes-accept-arbitrary-token-streams (kudos to @jplatte for pointing this out)
I propose changing the derive props macro attributes from props to prop_or_else, prop_or_default. Reference: https://doc.rust-lang.org/reference/procedural-macros.html#derive-macro-helper-attributes I feel that or, or_else and or_default naming is more Rust-y and the or_else helps inform developers that the default expression for a prop will not be run at runtime unless a prop is not present.
It's supposed to be default = …, not default: …, right?
@jplatte I believe either is supported by Rust now. I thought default: ... looked nicer but default = ... is fine too
Yeah, either should be possible. I've just never seen the colon syntax used in attributes. AFAIK all builtin attributes use = (e.g. #[path = "foo.rs"], #[cfg(feature = "feat")]).
@jplatte @mdtusz @AlephAlpha @hgzimmerman I just updated this issue to be a new proposal for how we handle props and would like input. This builds upon the work that @AlephAlpha already did in #881
I like the new proposal :)
We could maaaybe have #[prop_or_else(Callback::noop)] (fn) and #[prop_or(true)] (value) to mirror Options / Results API, but I don't know if that really makes things simpler.
Good call, that would probably be more in line with expected behavior. It'd be closer to Option's API
No comments from me. Looks like a great improvement for usability and grok-ability!
I'm trying to implement this. Should we support the old syntax for backward compatibility?
No need, would complicate things too much
Most helpful comment
I like the new proposal :)
We could maaaybe have
#[prop_or_else(Callback::noop)](fn) and#[prop_or(true)](value) to mirrorOptions /Results API, but I don't know if that really makes things simpler.