Skip to content

Direct React rendering

@inertiax/react can render Table state without importing Inertia or assuming how an application retrieves the next result.

Import the stylesheet once at the browser entry point:

import '@inertiax/react/styles.css';

That import provides the complete polished Table. If a design system will own the entire visual treatment, import @inertiax/react/base.css instead and follow the appearance contract.

Wrap Tables in InertiaXProvider:

import { InertiaXProvider } from '@inertiax/react';
export function App({ children }: { children: React.ReactNode }) {
return <InertiaXProvider>{children}</InertiaXProvider>;
}

The provider owns a portable runtime for that application root. It is also the application-level scope for theme, text, regions, custom leaf renderers, and events.

InertiaXRenderer accepts an envelope and does not read Inertia props or navigate through an application stack. It is appropriate for static data, tests, previews, renderer development, and applications with another explicit integration.

import { InertiaXProvider, InertiaXRenderer } from '@inertiax/react';
import { decodeEnvelope } from '@inertiax/protocol';
const envelope = decodeEnvelope(rawEnvelope);
export function Preview() {
return (
<InertiaXProvider>
<InertiaXRenderer envelope={envelope} />
</InertiaXProvider>
);
}

The default child is the complete built-in Table. Writing it explicitly is equivalent:

import { BuiltInTable, InertiaXRenderer } from '@inertiax/react';
<InertiaXRenderer envelope={envelope}>
<BuiltInTable />
</InertiaXRenderer>

Direct interactions use an in-memory integration: state remains canonical and validated, but no network request is invented. Changing search or pagination updates the direct envelope’s state; it does not query Laravel. The executable source is the @inertiax/react-renderer-lab.

For a Laravel/Inertia page, use the dedicated adapter instead. It turns state changes into partial reloads. See Inertia integration.

The renderer exposes hooks inside its Table context:

import { useTableController, useTableStatus } from '@inertiax/react';
function ReloadControl() {
const controller = useTableController();
const status = useTableStatus();
return (
<button disabled={status.type === 'pending'} onClick={() => controller.refresh()}>
Reload
</button>
);
}

Use the built-in regions when you only need to replace a finite part of the standard UI. Build a fully custom child only when the component really owns the complete rendering lifecycle.

Available context hooks include useTableController, useTableSnapshot, useTableState, useTableStatus, useTableEnvelope, and the customization hooks exported by the package.

InertiaXRenderer and the Inertia <InertiaX> component share these useful options:

  • debounceMs controls request scheduling for rapidly changing state.
  • controllerRef exposes the stable imperative Table controller.
  • table supplies component-local presentation customization.
  • pipeline supplies advanced component-local envelope transformations.
  • children can be the built-in Table, custom React content, or a function receiving the session.

The generic InertiaXIntegrationRenderer accepts a Core integration factory. It is intended for a real host integration—not as a reason for normal applications to reimplement the Inertia adapter.

Every raw envelope is decoded before rendering. Unsupported protocol versions and malformed top-level structures fail rather than producing a partially trusted Table.

Unknown custom leaf types use diagnosed fallback behavior by default. Set the runtime policy to fallback: 'error' when an unregistered custom cell or filter input must be fatal:

<InertiaXProvider runtimeOptions={{ diagnostics: { fallback: 'error' } }}>
{children}
</InertiaXProvider>

Learn how to register those leaf types in Custom types.