Efecto

La API effect complementa la API estado al proporcionar una mejor manera de reaccionar a múltiples cambios de estado en función de lo que necesita ejecutar.

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

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

La API state le permite suscribirse a cambios de su valor.

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

updateCount(10)

Esto es genial si desea realizar efectos secundarios relacionados con un solo estado. Para realizar efectos secundarios para múltiples estados, necesitará la API effect.

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

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

updateCount(10)

EffectUnSubscriber

Algunos efectos secundarios pueden permanecer ahí continuamente como un efecto global de algo específico. Otros deben limpiarse cada vez que desaparece el alcance donde están definidos.

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

cleanEffect()

¿Cómo funciona?

Cuando llama a StateGetter dentro de la función de devolución de llamada effect, effect se da cuenta del estado y esta detección se realiza de forma sincrónica.

El efecto llama a la devolución de llamada proporcionada tan pronto como se declara para que tenga conocimiento de los estados llamados en su interior.

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

El effect también realiza actualizaciones por lotes, lo que le permite actualizar varios estados a la vez y tener una sola reacción.

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 actualización por lotes es útil, pero el effect también comprende la inicialización, lo que le permite realizar un montón de cálculos durante la carga y ejecutarlo solo una vez que haya terminado.

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

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

Almacenamiento en caché

effect le permite devolver valores que se almacenan en caché y se proporcionan en la devolución de llamada para la próxima vez. Esto es excelente para rastrear cambios en las actualizaciones.

Por ejemplo, realice un efecto antirrebote en los cambios de valores de búsqueda.

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

efecto asíncrono

El effect funciona sincrónicamente. Así es como detecta los estados internos y almacena en caché los datos.

Sin embargo, la devolución de llamada que proporcione al effect puede ser asíncrona si realmente así lo desea.

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 lo hace, los datos almacenados en caché serán la promesa devuelta por la función y no los datos que devuelva de la devolución de llamada asíncrona. Esto significa que necesita resolver los datos almacenados en caché para obtener el valor.

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

    console.log(result)

    return result
})

efecto anidado

Puede anidar effect para realizar un seguimiento de diferentes valores. Esto permite que el cuerpo de su effect reaccione de forma independiente mientras diferentes efectos rastrean diferentes estados.

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

unsub() // clears all effects

Si desea borrar todos los efectos, puede darse de baja del effect más externo y éste se encargará de todos los effect secundarios por usted. Sin embargo, usted debe realizar un seguimiento de los efectos internos, ya que cada vez que se llama al efecto externo, se creará un nuevo efecto interno.

editar este documento