Saltar al contenido
SuperScheduler

ProducciónSe aplica aLite y Pro

Solución de problemas

La mayoría de los problemas tienen pocas causas: la hoja de estilos no está importada, el elemento anfitrión no tiene altura para `height="100%"`, el control se lee antes del montaje, o la vista muestra un día, el de hoy, mientras los datos están en otras fechas (`days` vale 1 por defecto y `startDate`, hoy). Comprueba también que las cadenas de fecha incluyan segundos, que los valores `resource` de los eventos coincidan exactamente con los ids de los recursos y que solo haya una copia de React instalada. Cada sección de abajo da el síntoma, la causa y la solución.

Verificado con v0.1.0 · revisado el 7 de octubre de 2026.md

Busca el síntoma, comprueba la causa y aplica la solución. Las secciones se aplican a Pro y a Lite salvo que nombren una edición. Si tu problema no aparece aquí, la referencia de la API enumera todas las opciones implementadas con su valor por defecto, y su sección de APIs reservadas enumera lo que tiene tipos pero no está implementado.

El scheduler se renderiza sin estilos

Síntoma. Aparecen filas y eventos, pero sin líneas de cuadrícula, sin colores y con las cabeceras desalineadas.

Causa. La hoja de estilos no está cargada, o está cargada la de la otra edición.

Solución. Impórtala una sola vez, en tu punto de entrada o en tu layout raíz: import 'super-scheduler/styles.css' para Pro, import 'super-scheduler-lite/styles.css' para Lite. La hoja de estilos de Pro vive en @layer super-scheduler con selectores de especificidad cero, así que cualquier regla tuya fuera de una capa prevalece; por eso, un reset amplio como * { border: 0 } también elimina los bordes de la librería (consulta Tailwind). unstyled desactiva a propósito las reglas visuales de la librería.

El scheduler mide 0 px de alto o no tiene la altura que le diste

Síntoma. No se ve nada, o la cuadrícula es más baja o más alta de lo esperado.

Causas y soluciones (Pro).

  • heightSpec vale 'Max' por defecto: height (600 por defecto) es un techo, y la cuadrícula mide lo que sumen sus filas, hasta ese valor. Dos filas con height={320} se renderizan con unos 130 px de alto. Usa heightSpec="Fixed" para una caja de altura constante.
  • height="100%" llena el elemento anfitrión del componente, un <div> sin estilos que SuperSchedulerComponent renderiza dentro de tu contenedor. Si ese <div> no tiene altura, el scheduler se queda en 0 px. Da a tu contenedor una altura definida y al elemento anfitrión el 100 %:
src/FillParent.tsxtsx
import { SuperSchedulerComponent } from 'super-scheduler'
import type { SuperScheduler } from 'super-scheduler'

interface Props {
  readonly rooms: SuperScheduler.ResourceData[]
  readonly events: SuperScheduler.EventData[]
}

// height="100%" fills the component's own host <div>: .fill sizes it (see the CSS below).
export function FillParent({ rooms, events }: Props) {
  return (
    <div className="fill">
      <SuperSchedulerComponent
        height="100%"
        startDate="2026-10-01"
        days={31}
        scale="Day"
        resources={rooms}
        events={events}
      />
    </div>
  )
}
csscss
.fill {
  height: 70vh; /* or a flex item with min-height: 0 */
}
.fill > div {
  height: 100%;
}
  • heightSpec="Auto" ajusta el control a su contenido sin barra de scroll vertical, así que lo que se desplaza es la página.
  • SchedulerPanes recibe su propio height numérico para el conjunto de los paneles.

En Lite, height es siempre un número fijo de píxeles (400 por defecto). En las dos ediciones, cuando el contenedor es un elemento flex, dale min-width: 0 en una fila (o min-height: 0 en una columna); si no, el tamaño mínimo automático del elemento flex puede dejar que la cuadrícula ensanche o alargue el layout en lugar de desplazarse.

ref.current o control es null

Causa. El control se crea en componentDidMount. Durante el primer render, en el servidor y después de desmontar, no hay ningún control activo: ref.current es null antes del montaje, y los objetos ref pasados como controlRef vuelven a null al desmontar.

Solución. Lee el control en efectos y en handlers de eventos, nunca durante el render. useSchedulerControl() devuelve el control como estado, así que un efecto puede depender de él:

src/Planning.tsxtsx
import { useEffect } from 'react'
import { SuperScheduler, SuperSchedulerComponent, useSchedulerControl } from 'super-scheduler'

const START = SuperScheduler.Date.today().addDays(-30)

export function Planning({ rooms }: { rooms: SuperScheduler.ResourceData[] }) {
  // `control` is null during the first render and the live control after mount.
  const { controlRef, control } = useSchedulerControl()

  useEffect(() => {
    if (control === null || control.disposed()) return
    control.scrollTo(SuperScheduler.Date.today(), false, 'middle')
  }, [control])

  return (
    <SuperSchedulerComponent
      controlRef={controlRef}
      startDate={START}
      days={90}
      scale="Day"
      resources={rooms}
    />
  )
}

En Pro, un controlRef de tipo función se llama con el control al montar y no se llama con null al desmontar. Una referencia al control guardada de antes de un desmontaje apunta a un control liberado: comprueba control.disposed() en el código asíncrono. Con la API imperativa, llama a init() antes que a nada; update() antes de init() lanza SuperScheduler.Exception.

No aparece nada en la cuadrícula

Comprueba esto por orden:

  1. Rango. days vale 1 por defecto y startDate, hoy. En Pro, scale también usa por defecto celdas de una hora ('CellDuration' con 60 minutos). Ajusta startDate, days y scale="Day" al periodo que cubren tus datos. Los conjuntos de datos de super-scheduler/datasets empiezan por defecto el 1 de enero de 2026.
  2. Cadenas de fecha. '2026-10-01T10:00' lanza SchedulerDate: "2026-10-01T10:00" is not an ISO 8601 date. Usa '2026-10-01' o '2026-10-01T10:00:00'. Los objetos Date nativos no pasan la comprobación de tipos; conviértelos (consulta fechas civiles).
  3. Ids de recurso. El resource de un evento tiene que ser exactamente igual al id de un recurso: 1 y '1' son distintos. Los eventos de recursos desconocidos no se dibujan.
  4. Árboles (Pro). Los children solo se renderizan con treeEnabled, y un padre solo muestra a sus hijos cuando tiene expanded: true.
  5. Filtros e indicadores. Un control.events.filter() o un control.rows.filter() activo, o hidden: true en el evento, lo ocultan.
  6. Estado vacío. Sin filas visibles, Pro muestra emptyState si lo has definido; Lite muestra «No resources» por defecto.

Los cambios no aparecen

  • Modificado en el sitio. El componente React solo reenvía una prop cuando cambia su identidad. Hacer push en el mismo array events o resources y volver a renderizar no envía nada. Pasa un array nuevo, o llama a control.update() después de una edición en el sitio.
  • El array cambia solo (Pro). El control adopta el array events que le pasas y lo modifica con splice cuando se añaden, eliminan o confirman eventos. Pasa una copia (useMemo(() => events.slice(), [events])) si ese array es estado compartido. Con un array congelado, como los que producen algunas librerías de estado en desarrollo, control.events.add, update y remove lanzan TypeError.
  • Actualizar un id desconocido. control.events.update(data) no hace nada cuando el id no está cargado; usa add para los eventos nuevos. add lanza una excepción si el id está duplicado.
  • Ha cambiado defaultEvents. Se lee una sola vez, en init(); los valores posteriores se ignoran con un aviso en desarrollo. Usa events controlados para los datos que cambian.
  • Hooks de celda (Pro). Los resultados de onBeforeCellRender se guardan en caché por celda. Si una celda depende de los eventos, pon cellsAutoUpdated: true en su recurso o llama a control.update().
  • Una prop eliminada. Una prop que desaparece entre renders vuelve a su valor por defecto.

Errores de import y subpaths incorrectos

Solo existen estos puntos de entrada; cualquier otro, como super-scheduler/dist/..., falla con un error de «not exported» de tu bundler o de Node:

  • Pro: super-scheduler, /styles.css, /react-render, /history, /minimap, /panes, /zoom-ui, /views, /ranges, /hooks, /tailwind, /datasets y /core.
  • Lite: solo super-scheduler-lite y super-scheduler-lite/styles.css. Los módulos de Pro no forman parte de Lite.

TypeScript los resuelve a través del campo exports del paquete con moduleResolution en bundler, node16 o nodenext; el ajuste antiguo node funciona gracias al typesVersions del paquete. Con noUncheckedSideEffectImports (TypeScript 5.6 y posteriores), importar una hoja de estilos necesita una declaración declare module '*.css', que ya aportan los tipos de cliente de los bundlers, como vite/client. super-scheduler/tailwind es un preset al estilo CommonJS: cárgalo con require('super-scheduler/tailwind'), o con un import por defecto si tu configuración admite la interoperabilidad con CommonJS.

Mensajes de la consola

MensajeSignificado
[super-scheduler] renderEvent needs the component from "super-scheduler/react-render"Se ha pasado una prop de render React (renderEvent, renderCell, eventHover, un handler onBefore*DomAdd...) al componente raíz. Importa SuperSchedulerComponent de super-scheduler/react-render.
super-scheduler: <feature> is not supported yetUna API reservada: con tipos, aceptada e inerte. Consulta APIs reservadas.
[super-scheduler] events wins over defaultEventsSe han pasado las dos props; se usa events.
[super-scheduler] defaultEvents is read only during init()Se ignora un nuevo valor de defaultEvents después del montaje.
SuperScheduler Lite: unsupported option "..."Lite lanza una excepción con cualquier opción que no implementa, también en producción. scale tiene que ser 'Day', y los children, frozen, split y columns de los recursos requieren Pro.

Pro solo muestra estos avisos cuando NODE_ENV no es production, y los de APIs reservadas solo una vez por función. Los errores de Lite se lanzan en todos los builds.

«Invalid hook call» o dos copias de React

Síntoma. «Invalid hook call» desde useSchedulerControl o useScheduler, contenido React en slots de renderizado que no ve tus providers de contexto, o errores de portales.

Causa. La librería resuelve una copia de React distinta de la de tu aplicación. Las dos ediciones declaran React como dependencia peer y nunca lo incluyen en su bundle, así que esto ocurre cuando la instalación o un enlace traen una segunda copia: un paquete enlazado o compilado en local, un monorepo con varias versiones de React o rangos peer no satisfechos (18.2 o posterior, o 19).

Solución. npm ls react react-dom tiene que mostrar una sola versión. Instala el tarball de Pro en lugar de enlazar una copia local. En Vite, añade resolve: { dedupe: ['react', 'react-dom'] }; en webpack, crea alias de react y react-dom hacia las copias de tu aplicación.

Errores de Content Security Policy

La librería no necesita scripts en línea ni estilos 'unsafe-inline': se carga como módulos y escribe la geometría mediante element.style. Si la consola informa de infracciones, comprueba tres cosas: script-src tiene que permitir los chunks que se cargan de forma diferida; las pequeñas imágenes SVG data: de la hoja de estilos de Pro necesitan img-src data:; y los atributos style en línea dentro de las cadenas HTML que pasas (html, bubbleHtml) se bloquean, así que usa clases. Los detalles y una política de ejemplo están en Renderizado en servidor.

Tailwind elimina bordes o sobrescribe el scheduler

El preflight de Tailwind v3 no está en ninguna capa y reinicia los bordes de todos los elementos, lo que se impone a las reglas en capa de la librería. Pon el preflight en una capa por debajo de SuperScheduler:

csscss
@layer tw-base, super-scheduler;

@import 'super-scheduler/styles.css';

@layer tw-base {
  @tailwind base;
}
@tailwind components;
@tailwind utilities;

Con Tailwind v4, declara el orden de las capas antes de los imports para que la librería quede entre base y tus utilidades:

csscss
@layer theme, base, super-scheduler, components, utilities;

@import 'tailwindcss';
@import 'super-scheduler/styles.css';

Consulta Temas para el preset de Tailwind y la correspondencia de tokens.

Otras sorpresas

  • Los eventos se ajustan a días completos (Pro). useEventBoxes vale 'Always' por defecto, lo que dibuja los eventos sobre celdas completas. Usa 'Never' para dibujar las horas exactas, y añade eventMoveByCell si el arrastre debe seguir anclado a las celdas.
  • Un clic deja una selección (Pro). Un clic en una celda vacía es una selección de una celda que se comunica a onTimeRangeSelected con origin: 'click', y su sombra se queda hasta la siguiente selección o un clic en otro sitio. Llama a args.control.clearSelection() en el handler.
  • Las teclas no hacen nada (Pro). keyboardEnabled vale false por defecto. keyboardMode="Full" también lo necesita. Con varios schedulers en una página, pon keyboardTarget="component".
  • Las fechas se han convertido en objetos (Pro). Después de un arrastre o un cambio de tamaño, el start y el end del evento son objetos SuperScheduler.Date. String(date) y JSON.stringify dan el valor ISO civil; date.toString('d MMM', locale) lo formatea.
  • Día de la semana incorrecto. SuperScheduler.Date#getDay() devuelve el día del mes. Usa getDayOfWeek() (0 es domingo) o dayOfWeekISO() (1 es lunes).

Guías relacionadas: Integración con React, Estado controlado, Renderizado en servidor y Virtualización y rendimiento.