信号は、2つの主要な目標を持つパフォーマンスのある州管理ライブラリです。
発表の投稿を読んで、どの問題が解決するか、どのようになったかについての詳細を確認してください。
# Just the core library
npm install @preact/signals-core
# If you're using Preact
npm install @preact/signals
# If you're using React
npm install @preact/signals-react
# If you're using Svelte
npm install @preact/signals-core
signal(initialValue)
signal.peek()
computed(fn)
effect(fn)
batch(fn)
untracked(fn)
信号ライブラリは、考えることができるビジネスロジックをモデル化するためのビルディングブロックである4つの関数を公開します。
signal(initialValue)
signal
関数は新しい信号を作成します。信号は、時間の経過とともに変化する値のためのコンテナです。 Signalの値を読み取るか、その.value
プロパティにアクセスして値更新を購読することができます。
import { signal } from "@preact/signals-core" ;
const counter = signal ( 0 ) ;
// Read value from signal, logs: 0
console . log ( counter . value ) ;
// Write to a signal
counter . value = 1 ;
信号への書き込みは、 .value
プロパティを設定することによって行われます。信号の値を変更すると、その信号に依存するすべての計算されたすべてのコンピューターと効果を同期して更新し、アプリ状態が常に一貫していることを確認します。
signal.peek()
まれに、以前の値に基づいて別の信号に書き込む効果がありますが、その効果をその信号にサブスクライブする必要はありません。信号の以前の値をsignal.peek()
を介して読み取ることができます。
const counter = signal ( 0 ) ;
const effectCount = signal ( 0 ) ;
effect ( ( ) => {
console . log ( counter . value ) ;
// Whenever this effect is triggered, increase `effectCount`.
// But we don't want this signal to react to `effectCount`
effectCount . value = effectCount . peek ( ) + 1 ;
} ) ;
本当に必要な場合はsignal.peek()
のみを使用する必要があることに注意してください。 signal.value
を介して信号の値を読み取ることは、ほとんどのシナリオで好ましい方法です。
computed(fn)
データは、多くの場合、既存のデータの他の部分から導き出されます。 computed
関数を使用すると、複数の信号の値を、追加のコンピューターに反応したり、使用したりできる新しい信号に組み合わせることができます。計算されたコールバックの変更内からアクセスされる信号が変更されると、計算されたコールバックが再実行され、その新しい戻り値が計算された信号の値になります。
import { signal , computed } from "@preact/signals-core" ;
const name = signal ( "Jane" ) ;
const surname = signal ( "Doe" ) ;
const fullName = computed ( ( ) => name . value + " " + surname . value ) ;
// Logs: "Jane Doe"
console . log ( fullName . value ) ;
// Updates flow through computed, but only if someone
// subscribes to it. More on that later.
name . value = "John" ;
// Logs: "John Doe"
console . log ( fullName . value ) ;
computed
コールバック関数内でアクセスされる信号は、計算された信号の依存関係として自動的にサブスクライブされ、追跡されます。
effect(fn)
effect
関数は、すべてを反応させる最後のピースです。コールバック関数内の信号にアクセスすると、その信号とその信号のすべての依存関係がアクティブになり、サブスクライブされます。その点で、それはcomputed(fn)
に非常に似ています。デフォルトでは、すべての更新は怠zyであるため、 effect
内部に信号にアクセスするまで更新されるものはありません。
import { signal , computed , effect } from "@preact/signals-core" ;
const name = signal ( "Jane" ) ;
const surname = signal ( "Doe" ) ;
const fullName = computed ( ( ) => name . value + " " + surname . value ) ;
// Logs: "Jane Doe"
effect ( ( ) => console . log ( fullName . value ) ) ;
// Updating one of its dependencies will automatically trigger
// the effect above, and will print "John Doe" to the console.
name . value = "John" ;
返された関数を呼び出すことにより、効果を破壊し、サブスクライブされたすべての信号から登録解除できます。
import { signal , computed , effect } from "@preact/signals-core" ;
const name = signal ( "Jane" ) ;
const surname = signal ( "Doe" ) ;
const fullName = computed ( ( ) => name . value + " " + surname . value ) ;
// Logs: "Jane Doe"
const dispose = effect ( ( ) => console . log ( fullName . value ) ) ;
// Destroy effect and subscriptions
dispose ( ) ;
// Update does nothing, because no one is subscribed anymore.
// Even the computed `fullName` signal won't change, because it knows
// that no one listens to it.
surname . value = "Doe 2" ;
エフェクトコールバックは、クリーンアップ機能を返す場合があります。クリーンアップ機能は、エフェクトコールバックが次に呼び出されたとき、またはエフェクトが廃棄されたときに最初に発生する場合に一度実行されます。
import { signal , effect } from "@preact/signals-core" ;
const count = signal ( 0 ) ;
const dispose = effect ( ( ) => {
const c = count . value ;
return ( ) => console . log ( `cleanup ${ c } ` ) ;
} ) ;
// Logs: cleanup 0
count . value = 1 ;
// Logs: cleanup 1
dispose ( ) ;
batch(fn)
batch
関数を使用すると、複数の信号の書き込みを1つのアップデートに組み合わせることができます。これは、コールバックが完了したときに最後にトリガーされます。
import { signal , computed , effect , batch } from "@preact/signals-core" ;
const name = signal ( "Jane" ) ;
const surname = signal ( "Doe" ) ;
const fullName = computed ( ( ) => name . value + " " + surname . value ) ;
// Logs: "Jane Doe"
effect ( ( ) => console . log ( fullName . value ) ) ;
// Combines both signal writes into one update. Once the callback
// returns the `effect` will trigger and we'll log "Foo Bar"
batch ( ( ) => {
name . value = "Foo" ;
surname . value = "Bar" ;
} ) ;
コールバック内に以前に書いた信号にアクセスしたり、別の信号によって無効にされた計算された信号にアクセスしたりすると、必要な依存関係を更新して、読み取った信号の現在の値を取得します。他のすべての無効な信号は、コールバック関数の最後に更新されます。
import { signal , computed , effect , batch } from "@preact/signals-core" ;
const counter = signal ( 0 ) ;
const double = computed ( ( ) => counter . value * 2 ) ;
const triple = computed ( ( ) => counter . value * 3 ) ;
effect ( ( ) => console . log ( double . value , triple . value ) ) ;
batch ( ( ) => {
counter . value = 1 ;
// Logs: 2, despite being inside batch, but `triple`
// will only update once the callback is complete
console . log ( double . value ) ;
} ) ;
// Now we reached the end of the batch and call the effect
バッチをネストすることができ、最も外側のバッチコールが完了すると更新がフラッシュされます。
import { signal , computed , effect , batch } from "@preact/signals-core" ;
const counter = signal ( 0 ) ;
effect ( ( ) => console . log ( counter . value ) ) ;
batch ( ( ) => {
batch ( ( ) => {
// Signal is invalidated, but update is not flushed because
// we're still inside another batch
counter . value = 1 ;
} ) ;
// Still not updated...
} ) ;
// Now the callback completed and we'll trigger the effect.
untracked(fn)
いくつかの信号を読み取ることができるが、それらを購読したくないコールバックを受信している場合は、 untracked
使用してサブスクリプションが発生しないようにすることができます。
const counter = signal ( 0 ) ;
const effectCount = signal ( 0 ) ;
const fn = ( ) => effectCount . value + 1 ;
effect ( ( ) => {
console . log ( counter . value ) ;
// Whenever this effect is triggered, run `fn` that gives new value
effectCount . value = untracked ( fn ) ;
} ) ;
MIT
、ライセンスファイルを参照してください。