Web components are not supported in server-side rendering (SSR) environments. This example assumes that your React application is running entirely on the browser (client-side only). If you attempt to use the chart component library within SSR frameworks (such as Next.js or Gatsby) without proper dynamic import or client-side rendering guards, you may encounter errors.
Instantiating the Nebuly Charts Client
To get started, you’ll first need to instantiate the Nebuly Charts client.
The following code snippet shows how to do this by importing the library and creating a client instance using your API key:
import NebulyReports from '@nebuly-ai/reports';
const client = new NebulyReports.Client({
publicKey: '<YOUR_NEBULY_PUBLIC_KEY>',
});
Providing the Nebuly Client via React Context
Next, it’s best practice in React to provide the Nebuly client throughout your app using React context.
This lets any component access the client instance via a custom hook, without having to pass it through props manually.
Here’s how you can create a provider component for the Nebuly client and a corresponding hook:
import NebulyReports from '@nebuly-ai/reports';
import { createContext, useContext, useMemo } from "react";
const NebulyClientContext = createContext<
InstanceType<typeof NebulyReports.Client>
>(null!);
export function NebulyClientProvider({
children,
}: {
children: React.ReactNode;
}) {
const value = useMemo(() => {
return new NebulyReports.Client({
baseUrl: "http://localhost:8080/api/external",
publicKey: "<YOUR_NEBULY_PUBLIC_KEY>",
});
}, []);
return (
<NebulyClientContext.Provider value={value}>
{children}
</NebulyClientContext.Provider>
);
}
export function useNebulyClient(): InstanceType<typeof NebulyReports.Client> {
const context = useContext(NebulyClientContext);
if (!context) {
throw new Error(
"useNebulyClient must be used within a NebulyClientProvider"
);
}
return context;
}
Registering Nebuly Web Components in React
To use Nebuly web components (such as charts) in your React application, you need to register them once—usually in your main entry point file.
This enables the custom HTML elements to be recognized by the browser.
The snippet below demonstrates how to do this within a React application setup:
import NebulyReports from '@nebuly-ai/reports/web';
import { createRoot } from 'react-dom/client';
import { NebulyClientProvider } from './NebulyClientProvider';
import App from './App';
NebulyReports.registerComponents();
const root = createRoot(document.getElementById('root')!);
root.render(
<NebulyClientProvider>
<App />
</NebulyClientProvider>
);
Displaying a List of Reports
If you want to display a list of available reports fetched from the Nebuly API, you can define a simple component that leverages the client, uses a data-fetching library like React Query, and handles loading and error states gracefully.
Here’s an example implementation:
import { useNebulyClient } from './NebulyClientProvider';
import { useNavigate } from '<your-favorite-router>';
import { useQuery } from '@tanstack/react-query';
export function ReportsList() {
const navigate = useNavigate();
const client = useNebulyClient();
const { data, error, status } = useQuery({
queryKey: ['reports'],
queryFn: () => client.listReports(),
});
const goToReport = (reportId: string) => {
navigate(`/report/${reportId}`);
};
if (error) {
return (
<div>
Error: {error.message}
</div>
);
}
if (status === 'loading') {
return (
<div>
Loading...
</div>
);
}
return (
<div>
{data.map((report) => (
<button
key={report.id}
onClick={() => goToReport(report.id)}
>
{report.title}
</button>
))}
</div>
);
}
Rendering a Report and Its Charts
Once a user selects a report, you’ll want to fetch detailed data for that report and render the associated charts.
The following example demonstrates how you might build a Report
component that retrieves report data, supports loading and error handling, and renders each chart using a separate ChartComponent
:
import type { ChartData } from '@nebuly-ai/reports';
import { useNebulyClient } from './NebulyClientProvider';
import { useQuery } from '@tanstack/react-query';
import { ChartComponent } from './ChartComponent';
export function Report({ reportId }: { reportId: string }) {
const client = useNebulyClient();
const { data, error, status } = useQuery({
queryKey: ['report', reportId],
queryFn: () => client.getReport({ reportId }),
});
if (error) {
return <div>Error: {error.message}</div>;
}
if (status === 'loading') {
return <div>Loading...</div>;
}
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
<h1>{data.title}</h1>
{data.charts.map((chart) => (
<div key={chart.id}>
<ChartComponent chart={chart} />
</div>
))}
</div>
);
}
ChartComponent: Rendering Nebuly Chart Types
The ChartComponent
helper function is responsible for rendering the appropriate Nebuly chart web component based on the chart type.
You can set up your chart option objects and extend the switch statement to support all the chart types you need:
import type { ChartData } from '@nebuly-ai/reports';
import type { ChartCustomizationOptions } from '@nebuly-ai/reports/web';
// Define your chart options as needed.
const lineOptions: ChartCustomizationOptions = { /* ... */ };
const metricOptions: ChartCustomizationOptions = { /* ... */ };
const horizontalBarOptions: ChartCustomizationOptions = { /* ... */ };
function ChartComponent({ chart }: { chart: ChartData }) {
switch (chart.type) {
case 'line_chart':
return <nebuly-line-chart data={JSON.stringify(chart.data)} options={JSON.stringify(lineOptions)} />;
case 'metric':
return <nebuly-metric-chart data={JSON.stringify(chart.data)} options={JSON.stringify(metricOptions)} />;
case 'horizontal_bar_chart':
return <nebuly-horizontal-bar-chart data={JSON.stringify(chart.data)} options={JSON.stringify(horizontalBarOptions)} />;
// Add additional chart type cases here as needed
default:
throw new Error(`Unknown chart type: ${chart.type}`);
}
}