Preguntas frecuentes
¿Cómo detengo los bucles de renderizado infinitos?
Si estás usando React, existe un error muy común que puede causar un renderizado infinito. Si no le das a tus columns, data o state una referencia estable, React entrará en un bucle infinito de re-renderizado ante cualquier cambio en el estado de la tabla.
¿Por qué sucede esto? ¿Es un error en TanStack Table? No, no lo es. Así es fundamentalmente como funciona React, y gestionar correctamente tus columnas, datos y estado evitará que esto suceda.
TanStack Table está diseñada para disparar un re-renderizado cada vez que cambian los data o columns que se pasan a la tabla, o cada vez que cambia cualquiera de los estados de la tabla.
No proporcionar referencias estables a
columnsodatapuede causar un bucle infinito de re-renderizados.
Error 1: Crear nuevas columnas o datos en cada renderizado
export default function MyComponent() {
//😵 MAL: ¡Esto causará un bucle infinito de re-renderizados porque `columns` se redefine como un nuevo array en cada renderizado!
const columns = [
// ...
];
//😵 MAL: ¡Esto causará un bucle infinito de re-renderizados porque `data` se redefine como un nuevo array en cada renderizado!
const data = [
// ...
];
//❌ Las columnas y los datos se definen en el mismo ámbito que `useReactTable` sin una referencia estable, ¡causará un bucle infinito!
const table = useReactTable({
columns,
data,
});
return <table>...</table>;
}
Solución 1: Referencias estables con useMemo o useState
En React, puedes dar una referencia "estable" a las variables definiéndolas fuera/arriba del componente, o usando useMemo o useState, o utilizando una librería de gestión de estado de terceros (como Redux o React Query 😉)
//✅ OK: Define las columnas fuera del componente
const columns = [
// ...
];
//✅ OK: Define los datos fuera del componente
const data = [
// ...
];
// Normalmente es más práctico definir las columnas y los datos dentro del componente, así que usa `useMemo` o `useState` para darles referencias estables
export default function MyComponent() {
//✅ BIEN: Esto no causará un bucle infinito de re-renderizados porque `columns` es una referencia estable
const columns = useMemo(() => [
// ...
], []);
//✅ BIEN: Esto no causará un bucle infinito de re-renderizados porque `data` es una referencia estable
const [data, setData] = useState(() => [
// ...
]);
// Las columnas y los datos se definen con una referencia estable, ¡no causarán un bucle infinito!
const table = useReactTable({
columns,
data,
});
return <table>...</table>;
}
Error 2: Mutar columnas o datos in situ
Incluso si les das a tus columns y data iniciales referencias estables, aún puedes encontrarte con bucles infinitos si los mutas in situ. Este es un error común que quizás no notes que estás cometiendo al principio. Algo tan simple como un data.filter() en línea puede causar un bucle infinito si no tienes cuidado.
export default function MyComponent() {
//✅ BIEN
const columns = useMemo(() => [
// ...
], []);
//✅ BIEN (React Query proporciona referencias estables a los datos automáticamente)
const { data, isLoading } = useQuery({
//...
});
const table = useReactTable({
columns,
//❌ MAL: Esto causará un bucle infinito de re-renderizados porque `data` se muta in situ (destruye la referencia estable)
data: data?.filter(d => d.isActive) ?? [],
});
return <table>...</table>;
}
Solución 2: Memoiza tus transformaciones de datos
Para evitar bucles infinitos, siempre debes memoizar tus transformaciones de datos. Esto se puede hacer con useMemo o similar.
export default function MyComponent() {
//✅ BIEN
const columns = useMemo(() => [
// ...
], []);
//✅ BIEN
const { data, isLoading } = useQuery({
//...
});
//✅ BIEN: Esto no causará un bucle infinito de re-renderizados porque `filteredData` está memoizado
const filteredData = useMemo(() => data?.filter(d => d.isActive) ?? [], [data]);
const table = useReactTable({
columns,
data: filteredData, // ¡referencia estable!
});
return <table>...</table>;
}
React Forget
Cuando se lance React Forget, estos problemas podrían ser cosa del pasado. O simplemente usa Solid.js... 🤓
¿Cómo evito que el estado de mi tabla se reinicie automáticamente cuando mis datos cambian?
La mayoría de los plugins utilizan un estado que debería reiniciarse normalmente cuando cambian las fuentes de datos, pero a veces necesitas suprimir que esto suceda si estás filtrando tus datos externamente, o editando tus datos de forma inmutable mientras los miras, o simplemente haciendo cualquier cosa externa con tus datos que no quieras que active el reinicio automático de una parte del estado de la tabla.
Para esas situaciones, cada plugin proporciona una forma de deshabilitar que el estado se reinicie automáticamente internamente cuando cambian los datos u otras dependencias de una parte del estado. Al establecer cualquiera de ellos en false, puedes evitar que se activen los reinicios automáticos.
Aquí hay un ejemplo basado en React de cómo evitar que prácticamente cada parte del estado cambie como lo haría normalmente mientras editamos la fuente de data para una tabla:
const [data, setData] = React.useState([])
const skipPageResetRef = React.useRef()
const updateData = newData => {
// Cuando los datos se actualizan con esta función, establece un indicador
// para deshabilitar todos los reinicios automáticos
skipPageResetRef.current = true
setData(newData)
}
React.useEffect(() => {
// Después de que la tabla se haya actualizado, siempre elimina el indicador
skipPageResetRef.current = false
})
useReactTable({
...
autoResetPageIndex: !skipPageResetRef.current,
autoResetExpanded: !skipPageResetRef.current,
})
Ahora, cuando actualicemos nuestros datos, ¡los estados de la tabla anteriores no se restablecerán automáticamente!