Yew: Properties 2.0 - Required unless annotated with default value

Created on 8 Feb 2020  Â·  9Comments  Â·  Source: yewstack/yew

Properties 2.0

Problem

Properties without #[props(required)] or #[props(default = "fn_name")] are implicitly set to their default value.

Proposal

Properties should be treated as required unless indicated otherwise

New syntax:

#[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>,
}

Old syntax:

#[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
}

Explanation

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.

proposal

Most helpful comment

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.

All 9 comments

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Boscop picture Boscop  Â·  4Comments

thienpow picture thienpow  Â·  3Comments

zethra picture zethra  Â·  5Comments

sackery picture sackery  Â·  3Comments

kellytk picture kellytk  Â·  4Comments