Skip to content

React SDK ​

React SDK for event tracking, error monitoring, and logging in React applications. Built on top of logstyx-js-core, the React SDK provides React-specific features including an ErrorBoundary component and a Trackable component for declarative event tracking.

Installation ​

bash
npm install github:devatlogstyx/logstyx-js-react#release

Quick Start ​

jsx
import useLogstyx from 'logstyx-js-react';

function App() {
  const logger = useLogstyx({
    projectId: 'your_project_id',
    endpoint: 'https://your-domain.com/api/v1/logs',
    captureUncaught: true,
    captureUnhandledRejections: true
  });

  const { ErrorBoundary, Trackable } = logger;

  return (
    <ErrorBoundary logger={logger}>
      <div>
        <Trackable 
          event="click" 
          context={{ page: 'home' }} 
          data={{ action: 'cta-click' }}>
          <button>Get Started</button>
        </Trackable>
      </div>
    </ErrorBoundary>
  );
}

Origin Configuration Required

Make sure to add your domain to the allowed origins in your Logstyx dashboard under Project Settings → Security.

Configuration ​

useLogstyx(options) ​

Initializes the Logstyx SDK and returns the logger instance with React components.

Required Options ​

projectId (string) ​

Your Logstyx project identifier.

javascript
projectId: 'proj_abc123xyz'

endpoint (string) ​

Your Logstyx API endpoint.

javascript
endpoint: 'https://logs.yourcompany.com/api/v1/logs'

Optional Options ​

captureUncaught (boolean) ​

Automatically capture uncaught JavaScript exceptions.

Default: false

javascript
captureUncaught: true

captureUnhandledRejections (boolean) ​

Automatically capture unhandled Promise rejections.

Default: false

javascript
captureUnhandledRejections: true

persistentSession (boolean) ​

Automatically add sessionId on context that persist over the visiting session.

Default: false

javascript
persistentSession: true

ErrorBoundary Component ​

React component that catches errors in child components and logs them to Logstyx. Prevents your entire app from crashing when an error occurs.

Basic Usage ​

jsx
import useLogstyx from 'logstyx-js-react';

function App() {
  const logger = useLogstyx({
    projectId: 'proj_abc123',
    endpoint: 'https://logs.example.com/api/v1/logs'
  });

  const { ErrorBoundary } = logger;

  return (
    <ErrorBoundary logger={logger}>
      <YourApp />
    </ErrorBoundary>
  );
}

With Custom Fallback UI ​

jsx
function CustomFallbackUI({ error, errorInfo }) {
  return (
    <div style={{ padding: '20px', textAlign: 'center' }}>
      <h2>Oops! Something went wrong.</h2>
      <p>{error?.message || 'An unknown error occurred'}</p>
      <details style={{ marginTop: '20px' }}>
        <summary>Click for technical details</summary>
        <pre style={{ textAlign: 'left', overflow: 'auto' }}>
          {errorInfo?.componentStack}
        </pre>
      </details>
      <button onClick={() => window.location.reload()}>
        Reload Page
      </button>
    </div>
  );
}

function App() {
  const logger = useLogstyx({ projectId: 'proj_abc123' });
  const { ErrorBoundary } = logger;

  return (
    <ErrorBoundary logger={logger} fallbackUI={CustomFallbackUI}>
      <YourApp />
    </ErrorBoundary>
  );
}

Multiple Error Boundaries ​

Use multiple ErrorBoundary components to isolate errors to specific parts of your app:

jsx
function App() {
  const logger = useLogstyx({ projectId: 'proj_abc123' });
  const { ErrorBoundary } = logger;

  return (
    <div>
      <Header />
      
      <ErrorBoundary logger={logger}>
        <Sidebar />
      </ErrorBoundary>

      <ErrorBoundary logger={logger}>
        <MainContent />
      </ErrorBoundary>

      <ErrorBoundary logger={logger}>
        <Footer />
      </ErrorBoundary>
    </div>
  );
}

Props ​

PropTypeRequiredDescription
loggerobjectYesThe logger instance from useLogstyx()
fallbackUIcomponentNoCustom error UI component
childrennodeYesChild components to protect

FallbackUI Props:

PropTypeDescription
errorErrorThe error that was caught
errorInfoobjectReact error info with componentStack

Trackable Component ​

Declarative component for tracking user interactions without writing event handlers.

Basic Usage ​

jsx
import useLogstyx from 'logstyx-js-react';

function MyComponent() {
  const logger = useLogstyx({ projectId: 'proj_abc123' });
  const { Trackable } = logger;

  return (
    <Trackable event="click" data={{ action: 'button_click' }}>
      <button>Click Me</button>
    </Trackable>
  );
}

With Context ​

Add persistent context that applies to all events:

jsx
<Trackable 
  event="click" 
  context={{ page: 'pricing', section: 'hero' }}
  data={{ plan: 'pro', action: 'signup' }}>
  <button>Start Free Trial</button>
</Trackable>

Multiple Events ​

Track multiple events on a single element:

jsx
<Trackable 
  event="focus blur change"
  context={{ field: 'email' }}
  data={{ formType: 'newsletter' }}>
  <input type="email" placeholder="Enter your email" />
</Trackable>

Custom Log Level ​

jsx
<Trackable 
  event="click" 
  level="warning"
  data={{ action: 'delete_draft' }}>
  <button>Delete Draft</button>
</Trackable>

Props ​

PropTypeRequiredDefaultDescription
eventstringYes-Space-separated DOM events (e.g., "click", "submit", "click submit")
contextobjectNo{}Context metadata
dataobjectNo{}Event-specific data
levelstringNo"info"Log level: "info", "warning", "error", "critical"
childrennodeYes-Single child element

Single Child Required

Trackable must have exactly one child element. Use a wrapper <div> if you need to track multiple elements.

Manual Logging ​

Use the logger instance directly for manual logging:

Log Levels ​

jsx
function MyComponent() {
  const logger = useLogstyx({ projectId: 'proj_abc123' });

  const handleAction = async () => {
    try {
      logger.info({ message: 'Action started', userId: '123' });
      
      const result = await performAction();
      
      logger.info({ 
        message: 'Action completed', 
        result: result.status 
      });
    } catch (error) {
      logger.error({ 
        message: 'Action failed', 
        error: error.message 
      });
    }
  };

  return <button onClick={handleAction}>Perform Action</button>;
}

Available Methods ​

jsx
// Info level
logger.info({ message: 'User logged in', userId: '123' });

// Warning level
logger.warning({ message: 'API rate limit approaching' });

// Error level
logger.error({ message: 'Payment failed', error: err.message });

// Critical level
logger.critical({ message: 'Database connection lost' });

// Custom level
logger.send('custom', { message: 'Custom event' });

Context Management ​

Set and clear context for multiple logs:

jsx
function UserProfile({ user }) {
  const logger = useLogstyx({ projectId: 'proj_abc123' });

  useEffect(() => {
    // Set context when component mounts
    logger.setContext({
      userId: user.id,
      userRole: user.role,
      page: 'profile'
    });

    // Clear context when component unmounts
    return () => logger.clearContext();
  }, [user.id]);

  const handleUpdate = () => {
    // This log will include the context
    logger.info({ message: 'Profile updated' });
  };

  return <button onClick={handleUpdate}>Update Profile</button>;
}

Complete Examples ​

E-commerce Tracking ​

jsx
import useLogstyx from 'logstyx-js-react';

function ProductPage({ product }) {
  const logger = useLogstyx({
    projectId: 'proj_abc123',
    endpoint: 'https://logs.example.com/api/v1/logs'
  });

  const { Trackable } = logger;

  return (
    <div>
      <h1>{product.name}</h1>

      <Trackable 
        event="click"
        context={{ page: 'product', productId: product.id }}
        data={{ action: 'add_to_cart', price: product.price }}>
        <button>Add to Cart</button>
      </Trackable>

      <Trackable 
        event="click"
        context={{ page: 'product', productId: product.id }}
        data={{ action: 'buy_now', price: product.price }}
        level="info">
        <button>Buy Now</button>
      </Trackable>

      <Trackable 
        event="click"
        context={{ page: 'product', productId: product.id }}
        data={{ action: 'view_details' }}>
        <a href={`/products/${product.id}/details`}>
          View Details
        </a>
      </Trackable>
    </div>
  );
}

Form Tracking ​

jsx
function SignupForm() {
  const logger = useLogstyx({ projectId: 'proj_abc123' });
  const { Trackable } = logger;

  const handleSubmit = async (e) => {
    e.preventDefault();
    
    logger.info({ 
      message: 'Signup form submitted',
      referrer: document.referrer 
    });

    try {
      await submitSignup(formData);
      logger.info({ message: 'Signup successful' });
    } catch (error) {
      logger.error({ 
        message: 'Signup failed', 
        error: error.message 
      });
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <Trackable 
        event="focus blur"
        context={{ field: 'email', form: 'signup' }}>
        <input type="email" name="email" required />
      </Trackable>

      <Trackable 
        event="focus blur"
        context={{ field: 'password', form: 'signup' }}>
        <input type="password" name="password" required />
      </Trackable>

      <button type="submit">Sign Up</button>
    </form>
  );
}

Feature Usage Tracking ​

jsx
function Dashboard() {
  const logger = useLogstyx({ projectId: 'proj_abc123' });
  const { Trackable } = logger;

  useEffect(() => {
    logger.setContext({
      page: 'dashboard',
      userId: currentUser.id
    });

    return () => logger.clearContext();
  }, []);

  return (
    <div>
      <Trackable 
        event="click"
        data={{ feature: 'export', format: 'csv' }}>
        <button>Export CSV</button>
      </Trackable>

      <Trackable 
        event="click"
        data={{ feature: 'filter', filterType: 'date' }}>
        <button>Filter by Date</button>
      </Trackable>

      <Trackable 
        event="click"
        data={{ feature: 'refresh' }}>
        <button>Refresh Data</button>
      </Trackable>
    </div>
  );
}

Error Handling with ErrorBoundary ​

jsx
import useLogstyx from 'logstyx-js-react';

function ErrorFallback({ error, errorInfo }) {
  return (
    <div className="error-container">
      <h1>Something went wrong</h1>
      <p>We've been notified and are working on it.</p>
      <details>
        <summary>Error details</summary>
        <p><strong>Error:</strong> {error?.message}</p>
        <pre>{errorInfo?.componentStack}</pre>
      </details>
      <button onClick={() => window.location.reload()}>
        Reload Page
      </button>
    </div>
  );
}

function App() {
  const logger = useLogstyx({
    projectId: 'proj_abc123',
    endpoint: 'https://logs.example.com/api/v1/logs',
    captureUncaught: true,
    captureUnhandledRejections: true,
    persistentSession:true
  });

  const { ErrorBoundary } = logger;

  return (
    <ErrorBoundary logger={logger} fallbackUI={ErrorFallback}>
      <Router>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </Router>
    </ErrorBoundary>
  );
}

Best Practices ​

1. Initialize Once at App Root ​

jsx
// ✅ Good: Initialize at app root
function App() {
  const logger = useLogstyx({ projectId: 'proj_abc123' });
  const { ErrorBoundary } = logger;

  return (
    <ErrorBoundary logger={logger}>
      <Router>
        <Routes>...</Routes>
      </Router>
    </ErrorBoundary>
  );
}

// ❌ Avoid: Re-initializing in every component
function MyComponent() {
  const logger = useLogstyx({ projectId: 'proj_abc123' }); // Don't do this
  // ...
}
jsx
// ✅ Good: Set context once
useEffect(() => {
  logger.setContext({ page: 'checkout', userId: user.id });
  return () => logger.clearContext();
}, []);

logger.info({ message: 'Step 1 completed' });
logger.info({ message: 'Step 2 completed' });

// ❌ Avoid: Repeating context
logger.info({ message: 'Step 1', page: 'checkout', userId: user.id });
logger.info({ message: 'Step 2', page: 'checkout', userId: user.id });

3. Trackable for Simple Interactions ​

jsx
// ✅ Good: Use Trackable for simple clicks
<Trackable event="click" data={{ action: 'download' }}>
  <button>Download</button>
</Trackable>

// ✅ Good: Use manual logging for complex logic
const handleComplexAction = async () => {
  logger.info({ message: 'Action started' });
  
  try {
    const result = await complexOperation();
    logger.info({ message: 'Action completed', result });
  } catch (error) {
    logger.error({ message: 'Action failed', error: error.message });
  }
};

4. Strategic ErrorBoundary Placement ​

jsx
// ✅ Good: Multiple boundaries for isolation
function App() {
  return (
    <div>
      <Header />
      
      <ErrorBoundary logger={logger}>
        <Sidebar />
      </ErrorBoundary>

      <ErrorBoundary logger={logger}>
        <MainContent />  {/* Error here won't crash Sidebar */}
      </ErrorBoundary>
    </div>
  );
}

5. Enable Error Capture in Production ​

jsx
const logger = useLogstyx({
  projectId: process.env.REACT_APP_LOGSTYX_PROJECT_ID,
  endpoint: process.env.REACT_APP_LOGSTYX_ENDPOINT,
  captureUncaught: process.env.NODE_ENV === 'production',
  captureUnhandledRejections: process.env.NODE_ENV === 'production'
  persistentSession:true,
});

6. Structured Data for Better Insights ​

jsx
// ❌ Avoid: Plain strings
logger.info('User clicked button');

// ✅ Better: Structured data
logger.info({
  message: 'User interaction',
  action: 'button_click',
  buttonId: 'cta-signup',
  page: 'landing',
  timestamp: Date.now()
});

Troubleshooting ​

Trackable Component Not Working ​

Issue: Events aren't being tracked

Solution: Ensure Trackable has exactly one child:

jsx
// ❌ Wrong: Multiple children
<Trackable event="click">
  <button>Button 1</button>
  <button>Button 2</button>
</Trackable>

// ✅ Correct: Single child
<Trackable event="click">
  <div>
    <button>Button 1</button>
    <button>Button 2</button>
  </div>
</Trackable>

ErrorBoundary Not Catching Errors ​

Issue: Errors aren't being caught

Solution: ErrorBoundary only catches errors in child components, not in:

  • Event handlers (use try-catch)
  • Asynchronous code (use try-catch)
  • Server-side rendering
  • Errors in ErrorBoundary itself
jsx
// ❌ Won't be caught by ErrorBoundary
<button onClick={() => {
  throw new Error('Click error');
}}>
  Click
</button>

// ✅ Will be caught
<button onClick={() => {
  try {
    riskyOperation();
  } catch (error) {
    logger.error({ message: 'Error', error: error.message });
  }
}}>
  Click
</button>

Context Not Persisting ​

Issue: Context is lost between logs

Solution: Make sure to set context before logging:

jsx
// Set context
logger.setContext({ userId: '123' });

// Context will be included in this log
logger.info({ message: 'Action' });

// Clear when done
logger.clearContext();

Origin Errors ​

Issue: Getting CORS or origin errors

Solution: Add your domain to allowed origins in Logstyx dashboard:

  1. Go to Project Detail Page
  2. Click Settings
  3. Add your domain to allowed origins
  4. Include both development (http://localhost:3000) and production domains

Integration with React Router ​

jsx
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import useLogstyx from 'logstyx-js-react';

function App() {
  const logger = useLogstyx({ projectId: 'proj_abc123' });
  const { ErrorBoundary } = logger;
  const location = useLocation();

  // Log page views
  useEffect(() => {
    logger.info({
      message: 'Page view',
      path: location.pathname,
      search: location.search
    });
  }, [location]);

  return (
    <ErrorBoundary logger={logger}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </ErrorBoundary>
  );
}

Released under the MIT License.