Сигналы - это исполнительная библиотека управления государством с двумя основными целями:
Прочитайте сообщение о объявлении, чтобы узнать больше о том, какие проблемы решаются и как это произошло.
# 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)
Библиотека сигналов разоблачает четыре функции, которые представляют собой строительные блоки для моделирования любой бизнес -логики, о которой вы можете подумать.
signal(initialValue)
Функция 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)
. По умолчанию все обновления ленивы, поэтому ничто не обновится, пока вы не получите доступ к сигналу внутри 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
функция позволяет объединить несколько сигнальных записей в одно обновление, которое запускается в конце, когда обратный вызов завершается.
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
, см. Файл лицензии.