RecoilJS en Práctica: Gestión de Estado Moderna en React

RecoilJS en Práctica: Gestión de Estado Moderna en React
RecoilJS es una biblioteca innovadora de gestión de estado para React, desarrollada por el equipo de Facebook. En un ecosistema lleno de opciones, RecoilJS destaca por su integración nativa con las últimas características de React, como Suspense y Concurrent Mode. En este artículo, exploraremos en la práctica cómo implementar una gestión de estado eficiente usando RecoilJS.
¿Por qué RecoilJS?
Tres características fundamentales hacen de RecoilJS una elección excepcional:
- Sintaxis Familiar: API intuitiva que sigue los patrones y principios de React
- Gestión Avanzada: Control eficiente de datos derivados y asíncronos a través de funciones puras
- Depuración Inteligente: Capacidad de observar múltiples aplicaciones sin comprometer el code-splitting
Demostración Práctica
Para demostrar el poder de RecoilJS, desarrollé una aplicación de gestión que integra usuarios, redes, tiendas y productos. La aplicación ejemplifica escenarios comunes en sistemas empresariales, como:
- Relaciones complejas entre entidades
- Carga asíncrona de datos
- Estados compartidos
- Actualizaciones en tiempo real
Conceptos Fundamentales
Antes de sumergirnos en el código, entendamos los conceptos esenciales de RecoilJS:
Atoms
Los Atoms son las unidades básicas de estado en RecoilJS. Similar al useState de React, pueden almacenar cualquier tipo de dato válido en JavaScript. Para acceder a un Atom, utilizamos el hook useRecoilState:
const usersAtom = atom<Array<User>>({
key: 'usersAtom',
default: usersQuery(),
});
Selectors
Los Selectors son transformadores de estado que pueden derivar datos de Atoms u otros Selectors. Funcionan como un sistema de caché inteligente:
const currentUserState = selector<User | null>({
key: 'currentUserState',
get: ({ get }) => get(currentUser),
set: ({ set, reset }, newValue) => {
if (newValue instanceof DefaultValue) {
return reset(currentUser);
}
if (newValue) {
set(usersAtom, (users) =>
users.map((u) => ({
...u,
selected: u.id === newValue.id,
}))
);
}
return set(currentUser, newValue);
},
});
RecoilRoot
RecoilRoot es el componente que encapsula todo el árbol de componentes que utilizarán RecoilJS:
function App() {
return (
<RecoilRoot>
<YourApp />
</RecoilRoot>
);
}
Implementación Detallada
Gestión de Usuarios
Comenzamos implementando la gestión de usuarios con un Atom simple:
const usersQuery = async () => {
const { data } = await getUsers();
return data;
};
export const usersAtom = atom<Array<User>>({
key: 'usersAtom',
default: usersQuery(),
});
Componente de Listado
Creamos un componente reutilizable para mostrar las entidades:
interface CardColumnProps<T extends BaseEntity> {
recoilSelector: RecoilValue<Array<T>>
children: (item: T) => ReactNode,
title: string,
}
function ListContainer<T extends BaseEntity>({
recoilSelector,
children,
title,
}: CardColumnProps<T>) {
const list = useRecoilValue(recoilSelector);
return (
<>
<Grid xs={12} item>
<Typography align="center" variant="h5">{title}</Typography>
</Grid>
<Grid xs={12} container item spacing={3}>
{list.map((item) => (
<Grid key={item.id} item xs={12}>
{children(item)}
</Grid>
))}
</Grid>
</>
);
}
Gestión de Estado Compartido
Una de las características más poderosas de RecoilJS es atomFamily, que permite crear estados dinámicos basados en parámetros:
export const chainsAtom = atomFamily<Array<Chain>, number>({
key: 'chainsAtom',
default: (userId: number) => chainsQuery(userId),
});
Actualizaciones en Tiempo Real
Implementamos un hook personalizado para facilitar la edición de estados:
function useModalHelper<T extends BaseEntity>(
selector: RecoilState<Array<T>>
): UseModalHelperReturn<T> {
const updateList = useSetRecoilState(selector);
const handleEdit = useCallback(
(values: T) => {
updateList((items) => {
const index = items.findIndex((p) => p.id === values.id);
return [...items.slice(0, index), values, ...items.slice(index + 1)];
});
},
[updateList]
);
return { handleEdit };
}
Conclusión
RecoilJS representa un avance significativo en la gestión de estado para aplicaciones React. Su API intuitiva, integración nativa con características modernas de React y capacidad para manejar estados complejos lo convierten en una excelente elección para proyectos de cualquier escala.
La combinación de Atoms, Selectors y atomFamily ofrece una solución elegante para los desafíos más comunes en el desarrollo de aplicaciones React, manteniendo el código limpio y mantenible.
Próximos Pasos
¡Pronto publicaré un artículo más profundo sobre patrones avanzados de edición de estado con RecoilJS. ¡Mantente atento!