The scheduler and the data grid are React components too, in @needless-ui/react: the same features, keyboard and accessibility as in Angular, the same stylesheet and the same MIT license. The other components are coming. They need React 19, and work with the Next.js App Router and with Vite.
Install
pnpm add @needless-ui/react @needless-ui/cssImport the styles
The components ship no styles. Import the stylesheet once, from a CSS file of your app.
/* app/globals.css in Next.js, src/index.css with Vite */
@layer reset, nui, app;
@import '@needless-ui/css';Layers work as in Angular: resets go in a layer before nui, and with Tailwind CSS, nui goes between Tailwind’s base and its utilities, as getting started shows.
A scheduler
Each component has its own entry point. The scheduler shows the events you pass, and calls you back when people move one or choose time for a new one: you keep the events.
A data grid
Describe the columns outside the component, so the grid doesn’t redo its work on every render. An edit calls onRowsChange with new rows, and methods such as the Excel export are on the grid’s ref.
The API in React’s terms
The React components follow the same specs as the Angular ones, so their APIs match, in React’s terms. The API pages list every prop: the scheduler’s and the data grid’s.
| Angular | React |
|---|---|
A model, [(view)] | State: view with onViewChange, or defaultView for the component to keep |
An output, (eventClick) | A callback, onEventClick |
A template, <ng-template nuiSchedulerEvent> | A function that draws, renderEvent |
A method, scheduler.next() | A method on the ref, ref.current.next() |
children, for tree data | getChildren: React keeps children for elements |
locale, by default the app’s LOCALE_ID | locale, by default en-US |
Server rendering
Both components render on the server and hydrate. The package marks them as client components, so a Server Component can render them with props that serialize, and helpers such as nuiSchedulerFromIcs run on the server. Callbacks can’t cross to the browser: a component that takes them goes in a client component of your own, like the two above.
What depends on the reader waits for the browser: the scheduler’s line for now, and which day is today. Give the scheduler a defaultDate when a server renders it, since the server’s today may not be the reader’s.