Data-Aware Components
Normalmente, al crear un app de React, un componente necesita un dato del API, ej. el usuario logueado, entonces hacés el fetch, manejás el estado de cargando y de un posible error, y listo, todo funciona y seguís armando tu app.
Pero muchas veces esta data la terminas necesitando en más componentes, lo que te da 2 opciones:
- Duplicas el código, o lo extraes a un hook, y haces el fetch cada vez que lo necesites
- Movés la lógica a un componente padre de todos los que lo necesiten y haces un fetch.
El primer caso es super ineficiente y nadie lo hace de verdad en producción, debido a la gran cantidad de requests duplicados que terminás haciendo.
El segundo es lo más común, y normalmente combinado con algo como Context o Redux para evitar pasar como props la data a cada componente que lo necesites, lo guardas en un lugar global y todos lo leen directo desde ahí con un solo useCurrentUser
hook.
Esto sirve, y podés seguir con esta estrategia un montón de tiempo, pero no por eso es lo mejor. En cambio podémos mejorar esto un montón creando data-aware components, veamos de que va.
Un data-aware component es un componente que hace algo similar al primer caso, es capaz de hacer el fetch, manejar estados de carga y error, y renderizarse, de forma totalmente independiente. Si ningún otro componente usa la misma data hace el fetch y listo, ningún otro se entera.
Pero, si más de un componente usa la misma data, el request se hace una sola vez y se comparte la cache del API entre todos los que lo necesiten. 🤯
Esto es genial, porque los componentes pueden de verdad ser independientes, es posible mover el componente a otra app y funciona.
Veamos un ejemplo:
function CurrentUserAvatar() {
const { data, error } = useCurrentUser()
if (error) return <ErrorAvatar />
if (!data) return <LoadingAvatar />
return <Avatar src={data.avatarUrl} src={data.fullName} />
}
Ese componente, lo podemos renderizar N veces y solo se va a hacer el fetch del usuario actual una vez.
Para esto, podemos usar dos libs, SWR o React Query, estas libs lo que tienen de especial es que poseen una cache donde guardan la data y evitan los requests duplicados automáticamente, en un rango de tiempo configurable.
SWR usa 2 segundos, así que todos los renders que usen la misma key de cache van a hacer un solo fetch, cualquier render luego de estos 2 segundos inicia un nuevo fetch, el cual actualiza la cache y con esto, todos los componentes que usen la misma key.
Esto último es muy importante, como todos comparten la misma cache cualquier componente que haga un fetch y actualice la data actualiza toda la app al mismo tiempo, así toda la app va a ser eventualmente consistente.