本文へスキップ

リアクティビティ

コンポーネント関数は、ウィンドウ(または親)がマウントされるときに 1 回実行されます。シグナルはツリー全体を作り直さずに、テキストとプロパティを最新に保ちます。

#リアクティブな状態

ui.CreateSignal でシグナルを作ります。テキストとプロパティで読みます:ui.Text("Count: ", count())、.Width(width())。イベントハンドラーは書き込みを自動的にバッチ処理します。

func TextExample() *ui.Element {
	count, setCount := ui.CreateSignal(0)
	return ui.View().Children(
		ui.Text(
			"Count: ",
			count(),
		).FontSize(20),
		ui.Button().Child("Increment").OnClick(func() { setCount(count() + 1) }),
	)
}

initial := count() はスナップショットです。値を更新し続けるときは、あとでシグナルを再度読んでください。シグナルを子として渡すこともできます。ui.Text("Count: ", count) は接頭辞を残し、数字だけを更新します。

カスタムコンポーネントは普通の int、string、構造体の引数を取ります。LineItem(product, quantity()) は quantity を購読し続けます。

#派生状態

他のシグナルから計算する値には ui.CreateMemo を使います。

func DerivedExample() *ui.Element {
	count, setCount := ui.CreateSignal(0)
	doubled := ui.CreateMemo(func() int { return count() * 2 })
	return ui.View().Children(
		ui.Text("Doubled: ", doubled()),
		ui.Button().Child("Increment").OnClick(func() { setCount(count() + 1) }),
	)
}

#副作用とクリーンアップ

購読やウィンドウタイトルなど、ツリーの外の作業には ui.CreateEffect を使います。マウント後に実行され、読んだ値が変わると再度実行されます。ui.OnCleanup は次の実行の前と、コンポーネントがなくなるときに実行されます。

func EffectExample() *ui.Element {
	topic, setTopic := ui.CreateSignal("Inbox")
	ui.CreateEffect(func() {
		current := topic()
		log.Print("Subscribe: ", current)
		ui.OnCleanup(func() { log.Print("Unsubscribe: ", current) })
	})
	return ui.View().Children(
		ui.Text("Watching: ", topic()),
		ui.Button().Child("Switch topic").OnClick(func() {
			if topic() == "Inbox" {
				setTopic("Archive")
			} else {
				setTopic("Inbox")
			}
		}),
	)
}

テキストとプロパティは直接更新します。effect の中で UI を作り直さないでください。

#更新のバッチ処理

クリックハンドラーはすでに書き込みをバッチします。ほかの場所では関連する書き込みを ui.Batch で包み、観察者には 1 つの結果だけが見えるようにします。ui.Untrack は購読せずにシグナルを読みます。シグナルの読み書きは UI ゴルーチンで行い、バックグラウンドの結果は ui.Async または native.Dispatch で届けます。

func BatchedExample() *ui.Element {
	first, setFirst := ui.CreateSignal("Ada")
	last, setLast := ui.CreateSignal("Lovelace")
	ui.CreateEffect(func() { log.Print(first() + " " + last()) })
	applyProfile := func() {
		ui.Batch(func() {
			setFirst("Grace")
			setLast("Hopper")
		})
	}
	return ui.View().Children(
		ui.Text(first(), " ", last()),
		ui.Button().Child("Apply profile").OnClick(applyProfile),
	)
}