@watchupltd/react
v1.0.3
Published
React integration for incident tracking with Provider pattern, hooks, and ErrorBoundary.
Readme
@watchupltd/react
React integration for incident tracking with Provider pattern, hooks, and ErrorBoundary.
Installation
npm install @watchupltd/reactQuick Start
import { IncidentProvider, useIncident } from '@watchupltd/react';
function App() {
return (
<IncidentProvider
apiKey="your-api-key"
projectId="your-project-id"
environment="production"
>
<YourApp />
</IncidentProvider>
);
}
function Component() {
const { captureError, captureMessage, setUser } = useIncident();
const handleClick = async () => {
try {
await riskyOperation();
} catch (error) {
captureError(error, {
tags: { component: 'MyComponent' }
});
}
};
return <button onClick={handleClick}>Click me</button>;
}What It Tracks
Automatic Tracking
- React ErrorBoundary: Catches component rendering errors
- Global JavaScript Errors: Via
window.onerror - Unhandled Promise Rejections: Via
window.onunhandledrejection - Console Errors: Optional via
captureConsoleErrorsprop
Manual Tracking
- Custom errors via
captureError() - Log messages via
captureMessage() - User context via
setUser() - Tags via
setTag()/setTags() - Breadcrumbs via
addBreadcrumb()
Components
<IncidentProvider>
Wrap your app with this provider to enable incident tracking.
<IncidentProvider
apiKey="your-api-key"
projectId="your-project-id"
environment="production"
captureConsoleErrors={true}
batchInterval={5000}
maxBatchSize={10}
>
<App />
</IncidentProvider>Props:
apiKey(required): Your API keyprojectId(required): Your project IDenvironment(optional): Environment name (default: 'production')captureConsoleErrors(optional): Capture console.error callsbatchInterval(optional): Batch interval in ms (default: 5000)maxBatchSize(optional): Max events per batch (default: 10)maxRetries(optional): Max retry attempts (default: 3)enabled(optional): Enable/disable SDK (default: true)
<ErrorBoundary>
Automatically included in <IncidentProvider>. You can also use it standalone:
import { ErrorBoundary } from '@watchupltd/react';
<ErrorBoundary
client={client}
fallback={<div>Something went wrong</div>}
>
<YourComponent />
</ErrorBoundary>Hooks
useIncident()
Access incident tracking methods in any component.
const {
captureError,
captureMessage,
addBreadcrumb,
setUser,
setTag,
setTags
} = useIncident();Methods:
captureError(error: Error, context?: EventContext): Promise<string | null>
try {
await fetchData();
} catch (error) {
captureError(error, {
tags: { api: 'users' },
extra: { userId: '123' }
});
}captureMessage(message: string, level?: SeverityLevel, context?: EventContext): Promise<string | null>
captureMessage('User completed checkout', 'info', {
tags: { flow: 'checkout' }
});addBreadcrumb(breadcrumb: Breadcrumb): void
addBreadcrumb({
message: 'User clicked submit',
category: 'user-action',
level: 'info'
});setUser(user: User | null): void
setUser({
id: 'user-123',
email: '[email protected]',
username: 'john_doe'
});setTag(key: string, value: string): void
setTag('version', '1.2.3');setTags(tags: Record<string, string>): void
setTags({
browser: 'chrome',
os: 'windows'
});Examples
Track User Actions
function CheckoutButton() {
const { addBreadcrumb, captureMessage } = useIncident();
const handleCheckout = () => {
addBreadcrumb({
message: 'User initiated checkout',
category: 'user-action'
});
processCheckout()
.then(() => {
captureMessage('Checkout completed', 'info');
});
};
return <button onClick={handleCheckout}>Checkout</button>;
}Set User Context on Login
function LoginForm() {
const { setUser } = useIncident();
const handleLogin = async (credentials) => {
const user = await login(credentials);
setUser({
id: user.id,
email: user.email,
username: user.username
});
};
return <form onSubmit={handleLogin}>...</form>;
}Track API Errors
function DataFetcher() {
const { captureError, addBreadcrumb } = useIncident();
useEffect(() => {
addBreadcrumb({
message: 'Fetching user data',
category: 'api'
});
fetchUserData()
.catch(error => {
captureError(error, {
tags: { api: 'users', endpoint: '/api/users' },
extra: { timestamp: Date.now() }
});
});
}, []);
return <div>...</div>;
}Custom Error Boundary Fallback
<IncidentProvider
apiKey="your-api-key"
projectId="your-project-id"
fallback={
<div style={{ padding: '20px', textAlign: 'center' }}>
<h1>Oops! Something went wrong</h1>
<p>We've been notified and are working on it.</p>
<button onClick={() => window.location.reload()}>
Reload Page
</button>
</div>
}
>
<App />
</IncidentProvider>SSR Support
The SDK is SSR-safe and won't break server-side rendering. Browser-specific APIs are only accessed on the client side.
TypeScript Support
Full TypeScript support with type definitions included.
import type { IncidentConfig, SeverityLevel, User, Breadcrumb } from '@watchupltd/react';Data Models
Event Model
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"project_id": "proj_abc123",
"fingerprint": "a1b2c3d4e5f6...",
"title": "Error",
"message": "Something went wrong",
"stack_trace": "Error: Something went wrong\n at Component (App.tsx:10:5)",
"service": "frontend",
"environment": "production",
"severity": "error",
"timestamp": 1678901234567,
"platform": "javascript",
"release": "1.2.3",
"metadata": {
"react": {
"componentStack": "[email protected]:10"
}
},
"user": {
"id": "user-123",
"email": "[email protected]",
"username": "john_doe"
},
"tags": {
"component": "App",
"version": "1.2.3"
},
"breadcrumbs": [
{
"timestamp": 1678901230000,
"message": "Component mounted",
"category": "react",
"level": "info",
"data": {"component": "App"}
}
],
"context": {
"react": {
"version": "18.2.0"
}
}
}User Model
{
"id": "user-123",
"email": "[email protected]",
"username": "john_doe",
"ip_address": "192.168.1.1"
}Breadcrumb Model
{
"timestamp": 1678901234567,
"message": "User action description",
"category": "user-action | navigation | http | database | console",
"level": "fatal | error | warning | info | debug",
"data": {
"key": "value"
}
}License
MIT
