Zum Inhalt springen
SuperScheduler

ProduktionGilt fürLite und Pro

Fehlerbehebung

Die meisten Probleme haben wenige Ursachen: Das Stylesheet ist nicht importiert, der Host hat keine Höhe für `height="100%"`, das Control wird vor dem Mount gelesen, oder die Ansicht zeigt einen Tag ab heute, während die Daten woanders liegen (`days` ist standardmäßig 1 und `startDate` heute). Prüfen Sie außerdem, dass Datums-Strings Sekunden enthalten, dass die `resource`-Werte der Ereignisse genau den Ressourcen-IDs entsprechen und dass nur eine Kopie von React installiert ist. Jeder Abschnitt unten nennt Symptom, Ursache und Lösung.

Geprüft mit v0.1.0 · überarbeitet am 7. Oktober 2026.md

Suchen Sie das Symptom, prüfen Sie die Ursache, wenden Sie die Lösung an. Die Abschnitte gelten für Pro und Lite, sofern sie keine Edition nennen. Steht Ihr Problem nicht hier, führt die API-Referenz jede implementierte Option mit ihrem Standardwert auf, und ihr Abschnitt zu reservierten APIs nennt, was typisiert, aber nicht implementiert ist.

Der Planer erscheint ohne Styles

Symptom. Zeilen und Ereignisse erscheinen, aber ohne Rasterlinien, Farben oder ausgerichtete Köpfe.

Ursache. Das Stylesheet ist nicht geladen, oder es ist das Stylesheet der falschen Edition geladen.

Lösung. Importieren Sie es einmal, in Ihrem Einstiegspunkt oder Root-Layout: import 'super-scheduler/styles.css' für Pro, import 'super-scheduler-lite/styles.css' für Lite. Das Pro-Stylesheet liegt in @layer super-scheduler mit Selektoren ohne Spezifität, sodass jede Ihrer Regeln außerhalb eines Layers gewinnt; ein breiter Reset wie * { border: 0 } entfernt daher auch die Rahmen der Bibliothek (siehe Tailwind). unstyled schaltet die visuellen Regeln der Bibliothek absichtlich ab.

Der Planer ist 0 px hoch oder nicht so hoch wie eingestellt

Symptom. Nichts ist zu sehen, oder das Raster ist niedriger oder höher als erwartet.

Ursachen und Lösungen (Pro).

  • heightSpec steht standardmäßig auf 'Max': height (standardmäßig 600) ist eine Obergrenze, und das Raster ist so hoch wie seine Zeilen, bis zu diesem Wert. Zwei Zeilen mit height={320} werden etwa 130 px hoch gerendert. Verwenden Sie heightSpec="Fixed" für einen Kasten mit konstanter Höhe.
  • height="100%" füllt das Host-Element der Komponente, ein ungestyltes <div>, das SuperSchedulerComponent innerhalb Ihres Wrappers rendert. Hat dieses <div> keine Höhe, fällt der Planer auf 0 px zusammen. Geben Sie dem Wrapper eine feste Höhe und dem Host 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" bemisst das Control nach seinem Inhalt, ohne vertikale Bildlaufleiste; stattdessen scrollt die Seite.
  • SchedulerPanes nimmt eine eigene numerische height für alle Bereiche zusammen.

In Lite ist height immer eine feste Pixelzahl (standardmäßig 400). Wenn der Wrapper ein Flex-Element ist, geben Sie ihm in beiden Editionen min-width: 0 in einer Zeile (oder min-height: 0 in einer Spalte); sonst kann die automatische Mindestgröße des Flex-Elements dazu führen, dass das Raster das Layout verbreitert oder verlängert, statt zu scrollen.

ref.current oder control ist null

Ursache. Das Control wird in componentDidMount erzeugt. Beim ersten Rendern, auf dem Server und nach dem Unmount gibt es kein aktives Control: ref.current ist vor dem Mount null, und Ref-Objekte, die als controlRef übergeben werden, werden beim Unmount auf null zurückgesetzt.

Lösung. Lesen Sie das Control in Effects und Event-Handlern, nie während des Renderns. useSchedulerControl() gibt das Control als State zurück, sodass ein Effect davon abhängen kann:

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}
    />
  )
}

In Pro wird eine Funktion als controlRef beim Mount mit dem Control aufgerufen und beim Unmount nicht mit null. Eine Referenz auf das Control, die aus der Zeit vor einem Unmount stammt, zeigt auf ein freigegebenes Control: Prüfen Sie in asynchronem Code control.disposed(). Mit der imperativen API rufen Sie vor allem anderen init() auf; update() vor init() wirft SuperScheduler.Exception.

Im Raster ist nichts zu sehen

Prüfen Sie diese Punkte der Reihe nach:

  1. Zeitraum. days ist standardmäßig 1 und startDate heute. In Pro steht scale außerdem standardmäßig auf Stundenzellen ('CellDuration' mit 60 Minuten). Setzen Sie startDate, days und scale="Day" auf den Zeitraum, den Ihre Daten abdecken. Datensätze aus super-scheduler/datasets beginnen standardmäßig am 2026-01-01.
  2. Datums-Strings. '2026-10-01T10:00' wirft SchedulerDate: "2026-10-01T10:00" is not an ISO 8601 date. Verwenden Sie '2026-10-01' oder '2026-10-01T10:00:00'. Native Date-Objekte bestehen die Typprüfung nicht; wandeln Sie sie um (siehe bürgerliche Zeit).
  3. Ressourcen-IDs. Die resource eines Ereignisses muss genau einer Ressourcen-id entsprechen: 1 und '1' sind verschieden. Ereignisse unbekannter Ressourcen werden nicht gezeichnet.
  4. Bäume (Pro). children werden nur mit treeEnabled gerendert, und ein Elternelement zeigt seine Kinder nur, wenn es expanded: true hat.
  5. Filter und Flags. Ein aktives control.events.filter() oder control.rows.filter() oder hidden: true am Ereignis blendet es aus.
  6. Leerzustand. Ohne sichtbare Zeilen zeigt Pro emptyState, falls Sie es gesetzt haben; Lite zeigt standardmäßig „No resources“.

Änderungen erscheinen nicht

  • Direkt verändert. Die React-Komponente leitet eine Prop nur weiter, wenn sich ihre Identität ändert. Etwas in dasselbe events- oder resources-Array zu pushen und neu zu rendern, sendet nichts. Übergeben Sie ein neues Array oder rufen Sie nach einer direkten Änderung control.update() auf.
  • Das Array ändert sich von selbst (Pro). Das Control übernimmt das events-Array, das Sie übergeben, und verändert es per splice, wenn Ereignisse hinzugefügt, entfernt oder übernommen werden. Übergeben Sie eine Kopie (useMemo(() => events.slice(), [events])), wenn dieses Array geteilter State ist. Ein eingefrorenes Array, wie es manche State-Bibliotheken in der Entwicklung erzeugen, lässt control.events.add, update und remove einen TypeError werfen.
  • Eine unbekannte ID aktualisieren. control.events.update(data) bewirkt nichts, wenn die ID nicht geladen ist; verwenden Sie add für neue Ereignisse. add wirft bei einer doppelten ID.
  • defaultEvents geändert. Es wird einmal bei init() gelesen; spätere Werte werden mit einer Warnung in der Entwicklung ignoriert. Verwenden Sie kontrollierte events für Daten, die sich ändern.
  • Zell-Hooks (Pro). Ergebnisse von onBeforeCellRender werden pro Zelle zwischengespeichert. Hängt eine Zelle von Ereignissen ab, setzen Sie cellsAutoUpdated: true an ihrer Ressource oder rufen Sie control.update() auf.
  • Eine Prop entfernt. Eine Prop, die zwischen zwei Renderings verschwindet, kehrt zu ihrem Standardwert zurück.

Importfehler und falsche Subpaths

Nur diese Einstiegspunkte existieren; alles andere, etwa super-scheduler/dist/..., scheitert mit einem „not exported“-Fehler Ihres Bundlers oder von Node:

  • Pro: super-scheduler, /styles.css, /react-render, /history, /minimap, /panes, /zoom-ui, /views, /ranges, /hooks, /tailwind, /datasets und /core.
  • Lite: nur super-scheduler-lite und super-scheduler-lite/styles.css. Pro-Module sind nicht Teil von Lite.

TypeScript löst diese über die exports des Pakets auf, wenn moduleResolution auf bundler, node16 oder nodenext steht; die ältere Einstellung node funktioniert über die typesVersions des Pakets. Mit noUncheckedSideEffectImports (TypeScript 5.6 und neuer) braucht ein Stylesheet-Import eine Deklaration declare module '*.css', die Client-Typen von Bundlern wie vite/client bereits mitbringen. super-scheduler/tailwind ist ein Preset im CommonJS-Stil: Laden Sie es mit require('super-scheduler/tailwind') oder mit einem Default-Import, wo Ihre Konfiguration CommonJS-Interop unterstützt.

Konsolenmeldungen

MeldungBedeutung
[super-scheduler] renderEvent needs the component from "super-scheduler/react-render"Eine React-Render-Prop (renderEvent, renderCell, eventHover, ein onBefore*DomAdd-Handler...) wurde an die Wurzelkomponente übergeben. Importieren Sie SuperSchedulerComponent aus super-scheduler/react-render.
super-scheduler: <feature> is not supported yetEine reservierte API: typisiert, akzeptiert, wirkungslos. Siehe Reservierte APIs.
[super-scheduler] events wins over defaultEventsBeide Props wurden übergeben; events wird verwendet.
[super-scheduler] defaultEvents is read only during init()Ein neuer Wert für defaultEvents nach dem Mount wird ignoriert.
SuperScheduler Lite: unsupported option "..."Lite wirft bei jeder Option, die es nicht implementiert, auch in Produktion. scale muss 'Day' sein, und children, frozen, split und columns von Ressourcen erfordern Pro.

Pro gibt diese Warnungen nur aus, wenn NODE_ENV nicht production ist, und Warnungen zu reservierten APIs nur einmal pro Funktion. Die Fehler von Lite werden in jedem Build geworfen.

„Invalid hook call“ oder zwei Kopien von React

Symptom. „Invalid hook call“ aus useSchedulerControl oder useScheduler, React-Inhalte in Render-Slots, die Ihre Context-Provider nicht sehen, oder Portal-Fehler.

Ursache. Die Bibliothek löst eine andere Kopie von React auf als Ihre App. Beide Editionen deklarieren React als Peer-Abhängigkeit und bündeln es nie; das passiert also, wenn die Installation oder ein Link eine zweite Kopie mitbringt: ein verlinktes oder lokal gebautes Paket, ein Monorepo mit mehreren React-Versionen oder nicht erfüllte Peer-Bereiche (18.2 oder neuer, oder 19).

Lösung. npm ls react react-dom muss eine einzige Version zeigen. Installieren Sie den Pro-Tarball, statt eine lokale Kopie zu verlinken. In Vite ergänzen Sie resolve: { dedupe: ['react', 'react-dom'] }; in webpack setzen Sie Aliase von react und react-dom auf die Kopien Ihrer App.

Fehler durch die Content Security Policy

Die Bibliothek braucht keine Inline-Skripte und keine 'unsafe-inline'-Styles: Sie lädt als Module und schreibt Geometrie über element.style. Meldet die Konsole Verstöße, prüfen Sie drei Dinge: Nachgeladene Chunks müssen von script-src erlaubt sein; die kleinen data:-SVG-Bilder des Pro-Stylesheets brauchen img-src data:; und Inline-style-Attribute in HTML-Strings, die Sie übergeben (html, bubbleHtml), werden blockiert, verwenden Sie also Klassen. Details und eine Beispiel-Policy finden Sie unter Server-Rendering.

Tailwind entfernt Rahmen oder überschreibt den Planer

Das Preflight von Tailwind v3 liegt in keinem Layer und setzt die Rahmen jedes Elements zurück, was die Regeln der Bibliothek in ihrem Layer schlägt. Legen Sie das Preflight in einen Layer unterhalb von SuperScheduler:

csscss
@layer tw-base, super-scheduler;

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

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

Mit Tailwind v4 deklarieren Sie die Reihenfolge der Layer vor den Imports, damit die Bibliothek zwischen base und Ihren Utilities liegt:

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

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

Zum Tailwind-Preset und zur Zuordnung der Tokens siehe Theming.

Weitere Überraschungen

  • Ereignisse rasten auf ganze Tage ein (Pro). useEventBoxes steht standardmäßig auf 'Always' und zeichnet Ereignisse über ganze Zellen. Verwenden Sie 'Never', um exakte Zeiten zu zeichnen, und ergänzen Sie eventMoveByCell, wenn das Ziehen an Zellen verankert bleiben soll.
  • Ein Klick hinterlässt eine Auswahl (Pro). Ein Klick auf eine leere Zelle ist eine Auswahl von einer Zelle, die an onTimeRangeSelected mit origin: 'click' gemeldet wird, und ihr Schatten bleibt bis zur nächsten Auswahl oder einem Klick an anderer Stelle stehen. Rufen Sie im Handler args.control.clearSelection() auf.
  • Tasten bewirken nichts (Pro). keyboardEnabled steht standardmäßig auf false. Auch keyboardMode="Full" braucht es. Bei mehreren Planern auf einer Seite setzen Sie keyboardTarget="component".
  • Datumswerte wurden zu Objekten (Pro). Nach einem Verschieben oder einer Dauer-Änderung sind start und end des Ereignisses SuperScheduler.Date-Objekte. String(date) und JSON.stringify liefern den ISO-Wert in bürgerlicher Zeit; date.toString('d MMM', locale) formatiert ihn.
  • Falscher Wochentag. SuperScheduler.Date#getDay() gibt den Tag des Monats zurück. Verwenden Sie getDayOfWeek() (0 ist Sonntag) oder dayOfWeekISO() (1 ist Montag).

Verwandte Anleitungen: React-Integration, Kontrollierter Zustand, Server-Rendering und Virtualisierung und Performance.