Efeito

A API effect complementa a API state fornecendo uma maneira melhor de reagir a múltiplas mudanças de estado com base no que você precisa executar.

typescript
type EffectSubscriber<T> = (value: T | undefined) => undefined | T
type EffectUnSubscriber = () => void

effect: <T>(sub: EffectSubscriber<T>) => EffectUnSubscriber

A API state permite que você assine alterações de seu valor.

javascript
const [count, updateCount] = state(0, () => {
    // react to changes
})

updateCount(10)

Isso é ótimo se você deseja causar efeitos colaterais relacionados a um único estado. Para realizar efeitos colaterais em vários estados, você precisará da API effect.

javascript
const [count, updateCount] = state(0)

effect(() => {
    // react to changes
})

updateCount(10)

EffectUnSubscriber

Alguns efeitos colaterais podem permanecer continuamente como um efeito global para algo específico. Outros precisam ser limpos sempre que o escopo onde estão definidos desaparece.

javascript
const cleanEffect = effect(() => {
    // react to changes
})

cleanEffect()

Como funciona?

Quando você chama um StateGetter dentro da função de retorno de chamada effect, o effect toma conhecimento do estado e essa detecção é feita de forma síncrona.

O efeito chama o retorno de chamada fornecido assim que é declarado, para que ele tome conhecimento dos estados chamados dentro dele.

javascript
effect(() => {
    console.log(count()) // will log right away
})

O effect também atualiza em lote, o que permite atualizar vários estados de uma vez e ter apenas uma única reação.

javascript
effect(() => {
    console.log(count(), total())
    // prints: 0 0 on initiation
    // prints: 1 1 on update of both values
})

setCount((prev) => prev + 1)
setTotal((prev) => prev + 1)

A atualização em lote é útil, mas o effect também entende a inicialização, o que permite fazer vários cálculos durante a carga e executá-los apenas uma vez após terminar.

javascript
effect(() => {
    console.log(count())
    // prints: 0 on initiation
    // print: 100 after the while loop completes
})

while (count() < 100) {
    setCount((prev) => prev + 1)
}

Cache

O effect permite retornar valores que são armazenados em cache e fornecidos no retorno de chamada para a próxima vez. Isso é ótimo para rastrear alterações nas atualizações.

Por exemplo, execute um efeito de rejeição nas alterações do valor de pesquisa.

javascript
const [search, setSearch] = state('')
const [searchResults, updateSearchResults] = state([])

effect((timer) => {
    clearTimeout(timer)

    // so the effect becomes aware of "search" state
    const searchValue = search()

    return setTimeout(async () => {
        const response = api.search({ searchValue })

        updateSearchResults(response.results)
    }, 300)
})

Efeito assíncrono

O effect funciona de forma síncrona. É assim que ele detecta os estados internos e armazena os dados em cache.

No entanto, o retorno de chamada fornecido ao effect pode ser assíncrono se você realmente desejar.

javascript
effect(async () => {
    try {
        const res = await fetch(
            `https://randomuser.me/api/?page=${count()}&results=10&seed=markup`
        )

        console.log(await res.json())
    } catch (e) {
        console.error(e)
    }
})

Se você fizer isso, os dados armazenados em cache serão a promessa retornada pela função e não os dados retornados do retorno de chamada assíncrono. Isso significa que você precisa resolver os dados armazenados em cache para obter o valor.

javascript
effect(async (res = Promise.resolve(0)) => {
    const result = count() + (await res)

    console.log(result)

    return result
})

Efeito aninhado

Você pode aninhar effect para rastrear valores diferentes. Isso permite que o corpo do seu effect reaja de forma independente enquanto diferentes efeitos rastreiam diferentes estados.

javascript
const unsub = effect(() => {
    console.log('outer', count())
    effect(() => {
        console.log('inner', count())
    })
})

unsub() // clears all effects

Se quiser limpar todos os efeitos, você pode cancelar a assinatura do effect mais externo e que cuidará de todos os filhos effect para você. No entanto, os efeitos internos devem ser rastreados por você, pois sempre que o efeito externo for chamado, um novo efeito interno será criado.

editar este documento