Signals é uma biblioteca de gerenciamento de estado de desempenho com dois objetivos principais:
Leia o post de anúncio para saber mais sobre quais problemas os sinais resolvem e como aconteceu.
# 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)
A Biblioteca Signals expõe quatro funções que são os blocos de construção para modelar qualquer lógica de negócios que você possa imaginar.
signal(initialValue)
A função signal
cria um novo sinal. Um sinal é um contêiner para um valor que pode mudar com o tempo. Você pode ler o valor de um sinal ou assinar atualizações de valor acessando sua propriedade .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 ;
A gravação em um sinal é feita definindo sua propriedade .value
. Alterar o valor de um sinal atualiza de forma síncrona todos os efeitos calculados e que depende desse sinal, garantindo que o estado do aplicativo seja sempre consistente.
signal.peek()
No caso raro de que você tem um efeito que deve gravar em outro sinal com base no valor anterior, mas você não deseja que o efeito seja inscrito nesse sinal, você pode ler o valor anterior de um sinais via 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 ;
} ) ;
Observe que você deve usar apenas signal.peek()
se realmente precisar. Ler o valor de um sinal via signal.value
é a maneira preferida na maioria dos cenários.
computed(fn)
Os dados geralmente são derivados de outras partes dos dados existentes. A função computed
permite combinar os valores de vários sinais em um novo sinal que pode ser reagido ou até usado por computados adicionais. Quando os sinais acessados dentro de uma alteração de retorno de chamada calculado, o retorno de chamada calculado é reexecionado e seu novo valor de retorno se torna o valor do sinal calculado.
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 ) ;
Qualquer sinal que seja acessado dentro da função de retorno de chamada computed
será automaticamente inscrito e rastreado como uma dependência do sinal calculado.
effect(fn)
A função effect
é a última peça que torna tudo reativo. Quando você acessa um sinal dentro de sua função de retorno de chamada, esse sinal e toda dependência do referido sinal serão ativados e inscritos. Nesse sentido, é muito semelhante ao computed(fn)
. Por padrão, todas as atualizações são preguiçosas, para que nada seja atualizado até você acessar um effect
de sinal.
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" ;
Você pode destruir um efeito e cancelar a inscrição de todos os sinais para a qual foi subscrito, chamando a função retornada.
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" ;
O retorno de chamada do efeito pode retornar uma função de limpeza. A função de limpeza é executada uma vez, quando o retorno de chamada do efeito é chamado ou quando o efeito for descartado, o que acontecer primeiro.
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)
A função batch
permite que você combine vários sinais de gravação em uma única atualização que é acionada no final quando o retorno de chamada ser concluído.
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" ;
} ) ;
Quando você acessa um sinal para o qual você escreveu anteriormente dentro do retorno de chamada ou acessa um sinal calculado que foi invalidado por outro sinal, atualizaremos apenas as dependências necessárias para obter o valor atual para o sinal do qual você leu. Todos os outros sinais invalidados serão atualizados no final da função de retorno de chamada.
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
Os lotes podem ser aninhados e as atualizações serão lavadas quando a chamada em lote mais externa for concluída.
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)
Caso quando você está recebendo um retorno de chamada que possa ler alguns sinais, mas você não deseja assinar -os, pode usar untracked
para impedir que qualquer assinatura aconteça.
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
, consulte o arquivo de licença.