Effet

L'API effect complète l'API state en offrant une meilleure façon de réagir à plusieurs changements d'état en fonction de ce que vous devez exécuter.

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

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

L'API state permet de s'abonner aux modifications de sa valeur.

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

updateCount(10)

C'est idéal si vous souhaitez effectuer des effets secondaires liés à un seul état. Pour effectuer des effets secondaires pour plusieurs états, vous aurez besoin de l'API effect.

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

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

updateCount(10)

EffectUnSubscriber

Certains effets secondaires peuvent persister de manière continue en tant qu’effet global lié à quelque chose de spécifique. D'autres doivent être nettoyés chaque fois que la portée dans laquelle ils sont définis disparaît.

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

cleanEffect()

Comment ça marche ?

Lorsque vous appelez un StateGetter dans la fonction de rappel effect, le effect prend conscience de l'état et cette détection se fait de manière synchrone.

L'effet appelle le rappel fourni dès qu'il est déclaré afin qu'il prenne conscience des états appelés à l'intérieur.

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

Le effect regroupe également les mises à jour, ce qui vous permet de mettre à jour plusieurs états à la fois et de n'avoir qu'une seule réaction.

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)

La mise à jour par lots est utile mais le effect comprend également l'initialisation qui vous permet d'effectuer un calcul groupé au chargement et de ne l'exécuter qu'une seule fois après avoir terminé.

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

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

Mise en cache

Le effect vous permet de renvoyer les valeurs mises en cache et fournies dans le rappel pour la prochaine fois. C’est idéal pour suivre les modifications au fil des mises à jour.

Par exemple, effectuez un effet anti-rebond sur les modifications de la valeur de recherche.

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)
})

Effet asynchrone

Le effect fonctionne de manière synchrone. C'est ainsi qu'il détecte les états à l'intérieur et met en cache les données.

Cependant, le rappel que vous fournissez au effect peut être asynchrone si vous le souhaitez vraiment.

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)
    }
})

Si vous le faites, les données mises en cache seront la promesse renvoyée par la fonction et non les données que vous renvoyez du rappel asynchrone. Cela signifie que vous devez résoudre les données mises en cache pour obtenir la valeur.

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

    console.log(result)

    return result
})

Effet imbriqué

Vous pouvez imbriquer effect pour suivre différentes valeurs. Cela permet au corps de votre effect de réagir indépendamment tandis que différents effets suivent différents états.

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

unsub() // clears all effects

Si vous souhaitez effacer tous les effets, vous pouvez vous désinscrire du effect le plus externe et qui s'occupera de tous les enfants effect pour vous. Cependant, vous devez suivre les effets internes car chaque fois que l'effet externe est appelé, un nouvel effet interne sera créé.

modifier ce document