メインコンテンツへスキップ
バージョン: 0.21

ライフサイクル

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

ライフサイクル

貢献する

ライフサイクルメソッド

作成

コンポーネントが作成されると、親コンポーネントからプロパティを受け取り、create メソッドに渡される Context<Self> 内に格納されます。プロパティはコンポーネントの状態の初期化に使用でき、「リンク」はコールバックの登録やコンポーネントへのメッセージの送信に使用できます。

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! {
// impl
}
}
}

表示

view メソッドを使用すると、コンポーネントをDOMにレンダリングする方法を記述できます。Rust関数を使用してHTMLのようなコードを記述すると非常に混乱する可能性があるため、YewはHTMLとSVGノードの宣言(属性とイベントリスナーの添付を含む)、および子コンポーネントをレンダリングするための便利な方法としてhtml!というマクロを提供します。このマクロは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コンポーネントライフサイクルメソッドは、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();
}
}
}
}
注意

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

更新

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

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 // Re-render
} else {
false
}
}
}
}

fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
// impl
}
}

}

変更

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

破棄

コンポーネントが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 {
// We are going to always request to re-render on any msg
true
}

fn view(&self, _ctx: &Context<Self>) -> Html {
// For this example it doesn't matter what is rendered
Html::default()
}

fn rendered(&mut self, ctx: &Context<Self>, _first_render: bool) {
// Request that the component is updated with this new msg
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型の定義を含めることが賢明です。メッセージ型の一貫した命名規則を採用すると役立つ場合があります。1つのオプション(唯一のオプションではありません)は、型をComponentNameMsgと名付けることです。たとえば、コンポーネントがHomepageと呼ばれている場合、型をHomepageMsgと呼ぶことができます。

enum Msg {
Click,
FormInput(String)
}

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

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

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