メインコンテンツまでスキップ
Version: Next

ライフサイクル

Component トレイトには、実装する必要がある多くのメソッドがあります。Yew はコンポーネントのライフサイクルのさまざまな段階でこれらのメソッドを呼び出します。

ライフサイクル

ドキュメントの改善

ライフサイクルメソッド

Create

コンポーネントが作成されるとき、それは親コンポーネントからプロパティを受け取り、それらは create メソッドに渡される Context<Self> に保存されます。これらのプロパティはコンポーネントの状態を初期化するために使用でき、"link" はコールバックを登録したり、コンポーネントにメッセージを送信したりするために使用できます。

use yew::{Component, Context, html, Html, Properties};

#[derive(PartialEq, Properties)]
pub struct Props;

pub struct MyComponent;

impl Component for MyComponent {
type Message = ();
type Properties = Props;

fn create(ctx: &Context<Self>) -> Self {
MyComponent
}

fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
// 具体的な実装
}
}
}

View

view メソッドは、コンポーネントがDOMにどのようにレンダリングされるべきかを記述することを可能にします。Rust関数を使用してHTMLに似たコードを書くことは非常に混乱する可能性があるため、Yewはhtml!マクロを提供しています。これにより、HTMLおよびSVGノードを宣言し(およびそれらに属性とイベントリスナーを追加し)、子コンポーネントを便利にレンダリングする方法が提供されます。このマクロは、ReactのJSXに似ています(プログラミング言語の違いを除いて)。一つの違いは、YewがSvelteのようなプロパティの簡略化された構文を提供している点です。ここでは、{onclick}とだけ書くことができ、onclick={onclick}と書く必要はありません。

use yew::{Component, Context, html, Html, Properties};

enum Msg {
Click,
}

#[derive(PartialEq, Properties)]
struct Props {
button_text: String,
}

struct MyComponent;

impl Component for MyComponent {
type Message = Msg;
type Properties = Props;

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn view(&self, ctx: &Context<Self>) -> Html {
let onclick = ctx.link().callback(|_| Msg::Click);
html! {
<button {onclick}>{ &ctx.props().button_text }</button>
}
}
}

使用方法の詳細については、html! ガイド を参照してください。

Rendered

rendered コンポーネントライフサイクルメソッドは、view が呼び出され、Yew がその結果を DOM にレンダリングした後、ブラウザがページを更新する前に呼び出されます。このメソッドは、コンポーネントが要素をレンダリングした後にのみ完了できる操作を実行したい場合に非常に便利です。また、first_render という名前のパラメーターがあり、この関数が最初のレンダリング時に呼び出されたか、後続のレンダリング時に呼び出されたかを判断するために使用できます。

use web_sys::HtmlInputElement;
use yew::{
Component, Context, html, Html, NodeRef,
};

pub struct MyComponent {
node_ref: NodeRef,
}

impl Component for MyComponent {
type Message = ();
type Properties = ();

fn create(_ctx: &Context<Self>) -> Self {
Self {
node_ref: NodeRef::default(),
}
}

fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<input ref={self.node_ref.clone()} type="text" />
}
}

fn rendered(&mut self, _ctx: &Context<Self>, first_render: bool) {
if first_render {
if let Some(input) = self.node_ref.cast::<HtmlInputElement>() {
input.focus();
}
}
}
}
note

このライフサイクルメソッドは実装する必要はなく、デフォルトでは何も実行しません。

Update

コンポーネントとの通信は主にメッセージを通じて行われ、これらのメッセージは update ライフサイクルメソッドによって処理されます。これにより、コンポーネントはメッセージに基づいて自身を更新し、再レンダリングが必要かどうかを判断できます。メッセージはイベントリスナー、子コンポーネント、エージェント、サービス、またはフューチャーによって送信されることがあります。

以下は update の実装例です:

use yew::{Component, Context, html, Html};

pub enum Msg {
SetInputEnabled(bool)
}

struct MyComponent {
input_enabled: bool,
}

impl Component for MyComponent {
type Message = Msg;
type Properties = ();

fn create(_ctx: &Context<Self>) -> Self {
Self {
input_enabled: false,
}
}

fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::SetInputEnabled(enabled) => {
if self.input_enabled != enabled {
self.input_enabled = enabled;
true // 再レンダリング
} else {
false
}
}
}
}

fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
// 具体的な実装
}
}

}

Changed

コンポーネントは親コンポーネントによって再レンダリングされることがあります。この場合、新しいプロパティを受け取り、再レンダリングが必要になることがあります。この設計により、プロパティの値を変更するだけで親子コンポーネント間の通信が促進されます。プロパティが変更されると、デフォルトの実装によりコンポーネントが再レンダリングされます。

Destroy

コンポーネントがDOMからアンマウントされると、Yewはdestroyライフサイクルメソッドを呼び出します。コンポーネントが破棄される前にクリーンアップ操作を実行する必要がある場合に便利です。このメソッドはオプションであり、デフォルトでは何も実行しません。

無限ループ

Yewのライフサイクルメソッドでは無限ループが発生する可能性がありますが、それは各レンダリング後に同じコンポーネントを更新し、その更新が再レンダリングを要求する場合にのみ発生します。

以下は簡単な例です:

use yew::{Context, Component, Html};

struct Comp;

impl Component for Comp {
type Message = ();
type Properties = ();

fn create(_ctx: &Context<Self>) -> Self {
Self
}

fn update(&mut self, _ctx: &Context<Self>, _msg: Self::Message) -> bool {
// どのメッセージでも常に再レンダリングを要求します
true
}

fn view(&self, _ctx: &Context<Self>) -> Html {
// レンダリングする内容は重要ではありません
Html::default()
}

fn rendered(&mut self, ctx: &Context<Self>, _first_render: bool) {
// この新しいメッセージを使用してコンポーネントを更新するように要求します
ctx.link().send_message(());
}
}

ここで何が起こっているのか見てみましょう:

  1. create 関数を使用してコンポーネントを作成します。
  2. view メソッドを呼び出して、Yew がブラウザの DOM にレンダリングする内容を知ることができます。
  3. rendered メソッドを呼び出し、Context リンクを使用して更新メッセージをスケジュールします。
  4. Yew がレンダリングフェーズを完了します。
  5. Yew はスケジュールされたイベントをチェックし、更新メッセージキューが空でないことを確認してメッセージを処理します。
  6. update メソッドを呼び出し、変更が発生し、コンポーネントが再レンダリングする必要があることを示す true を返します。
  7. ステップ2に戻ります。

rendered メソッドで更新をスケジュールすることは依然として可能であり、これは通常便利ですが、その際にはこのループをどのように終了させるかを考慮してください。

関連タイプ

Component トレイトには、MessageProperties の2つの関連タイプがあります。

impl Component for MyComponent {
type Message = Msg;
type Properties = Props;

// ...
}

Message タイプは、イベントが発生した後にコンポーネントにメッセージを送信するために使用されます。例えば、ユーザーがボタンをクリックしたり、ページをスクロールしたりしたときに何かを実行したい場合があります。コンポーネントは通常、複数のイベントに応答する必要があるため、Message タイプは通常、処理するイベントごとにバリアントを持つ列挙型です。

コードベースを整理する際には、Message タイプの定義をコンポーネントを定義する同じモジュールに含めるのが賢明です。メッセージタイプの命名に一貫した命名規則を採用することが役立つ場合があります。一つのオプション(唯一のオプションではありませんが)は、タイプを ComponentNameMsg と命名することです。例えば、コンポーネントが Homepage と名付けられている場合、タイプを HomepageMsg と命名することができます。

enum Msg {
Click,
FormInput(String)
}

Properties は、親コンポーネントからコンポーネントに渡される情報を表します。この型は Properties トレイトを実装する必要があり(通常はそれを派生させる)、特定のプロパティが必須かオプションかを指定できます。コンポーネントの作成および更新時にこの型が使用されます。コンポーネントのモジュール内で Props という名前の構造体を作成し、それをコンポーネントの Properties 型として使用するのが一般的な方法です。通常、"properties" は "props" と略されます。プロパティは親コンポーネントから渡されるため、アプリケーションのルートコンポーネントは通常、Properties 型として () を持ちます。ルートコンポーネントにプロパティを指定する場合は、App::mount_with_props メソッドを使用します。

ライフサイクルコンテキスト

すべてのコンポーネントライフサイクルメソッドは、コンテキストオブジェクトを受け取ります。このオブジェクトは、コンポーネントのスコープへの参照を提供し、コンポーネントにメッセージを送信したり、コンポーネントに渡されたプロパティを取得したりすることができます。