Migrar un listado viejo
De CustomDataTable controlado a SmartDataTable, el camino probado.
El camino que siguieron los cinco módulos admin de fesa.com.pa:
Crea la page action envolviendo la action existente: mapea pageIndex+1 → page, pageSize → limit, valida con el mismo zod schema, y lanza en vez de devolver { error }.
En la view, cambia el parsing manual por parseTableSearchParams (con paramPrefix si convivían varias tablas) y pasa initialData/initialTotalRows/initial*.
En el client, borra: urlState, navigate() con router.replace, los handlers de paginación/orden/búsqueda y los reducers de selección/expansión/visibilidad — todo eso ya lo hace la tabla.
Reemplaza <CustomDataTable data={...} …> por <SmartDataTable fetchFn={...} initialData={...} …> con configs "smart" (sin campos de estado).
Cambia cada router.refresh() post-mutación por silentRefetch() (+ router.refresh() si hay stats).
Bulk: getSelectedRowIds() / clearSelection() del ref en vez del estado propio.
Resultado típico
~300 líneas de plumbing menos por módulo, URL compartible, y cambiar de página deja de re-renderizar la página entera del servidor.