useEffect
An effect is a function tied to a specific component which runs on specific events or conditions.
non-blocking
The effect never delays the component being painted on-screen: neither the first paint nor the subsequent ones. Instead, effects start running after paints. This pattern aims to prioritize time-to-paint.
If the effect fetches data that is to be displayed on-screen, we have to deal with a first paint which won't have the data. We may either use a default value, or hide the value altogether by displaying a loader, a skeleton or nothing instead.
one or multiple runs
An effect runs at least once, after the first paint. The subsequent runs are conditionals. We may ask for the effect to run again:
- on every render
- or when one or several variables change in value, usually because they act as a dependency of that effect.
clean-up on unmount
The component may unmount at any time. We may perform clean-up in certain conditions:
- we have set-up a subscription and we want to cancel it.
- we have initiated a network fetch, and we want to disable the callback. We do that by setting a flag such as
isMountedto false, and ensures the callback does not mutate state when such flag is false.
synopsis
useEffect(f, [])
synchronous function
Even though the effect may start asynchronous tasks, it must itself come as a non-async function, that is, it must run and return immediately. As such, we may not use await directly in its body, but we may define an async function which uses await in its body and call that function instead.
function myEffect() {
/* effect content */
return /* clean up content */
}
dependencies
useEffect(effect, []) // once
useEffect(effect, [x]) // once, then when x changes
useEffect(effect) // on every render