Properties

プロパティを設定するとhtml!の中でコンポーネントを使う際に好きな値を渡したり、渡された値が使えます。

以下は最小のコンポーネントの書き方です。

use yew::prelude::*;

struct MyComponent {}

impl Component for MyComponent {
  type Message = ();
  type Properties = ();
  fn create(_props: Self::Properties, _link: ComponentLink<Self>) -> Self {
    Self {}
  }

  fn update(&mut self, _message: Self::Message) -> ShouldRender {
    true
  }

  fn view(&self) -> Html {
    html! {
      <div>{"Hello Yew"}</div>
    }
  }
}

これに対して以下の 2 点を修正します。

  1. type Properties()から適当な構造体にする
  2. MyComponentでプロパティ値を保持する

プロパティ構造体

プロパティとなる構造体にはderivePropertiesyew::prelude::*で取り込まれる)とCloneが必要です。

#[derive(Properties, Clone)]
struct Props {
  text: String
}

定義した構造体はComponentの関連型に設定してあげます。

type Properties = Props;

これで<Component text="foo" />のようにプロパティが渡せるようになりました。

初期設定

これでまでで渡せるようにはなりましたが、まだコンポーネント内では使えません。使えるようにするには、コンポーネント自体の構造体でプロパティの値を保持しなければなりません。

コンポーネント構造体MyComponentを以下のように修正します。

struct MyComponent {
  props: Props;
}

構造体を使うにはインスタンス化しなければなりませんが、それを行うのがcreate関数です。

create関数は自身のインスタンスを返すように実装します。また、第 1 引数として関連型に指定したPropertiesのインスタンスが渡される為、好きなようにプロパティ値を加工することができます。ただ今は渡ってきたプロパティをpropsにそのまま渡すだけとします。
create関数部分を修正します。

  fn create(props: Self::Properties, _link: ComponentLink<Self>) -> Self {
    Self { props }
  }

これでviewメソッドでself.props.textのようにアクセスできます。

Rc を使う

viewメソッドでプロパティ値を使う際、Copyトレイトが実装されている値はそのまま使えますが、そうでない場合は値をクローンして所有権が渡るようにしなければなりません。例えば例のtextようにStringcloneメソッドを呼ぶと新しい値が丸々コピーされてしまうので、沢山の子要素で使うなどした場合に無駄が多いです。

このような場合はRcを使うことでコピーを回避できます。その為に修正することはPropertiesStringRc<String>とするだけです。

#[derive(Properties, Clone)]
struct Props {
  text: std::rc::Rc<String>
}

あとはこのコンポーネントに値を渡す側のコンポーネントの同じ値もRc<String>となるようにして渡してあげるのみです。