Skip to content

React Integration

Integrate the Lingu widget into your React application using the useEffect hook pattern.

Basic Setup

tsx
import { useEffect } from 'react';

function App() {
  useEffect(() => {
    // Set widget configuration
    window.linguConfig = {
      apiKey: 'your-api-key-here',
      autoOpen: false
    };

    // Load the widget script
    const script = document.createElement('script');
    script.src = 'https://widget.uselingu.app/widget.js';
    script.async = true;
    document.body.appendChild(script);

    // Cleanup on unmount
    return () => {
      document.body.removeChild(script);
      // Remove widget container if exists
      const container = document.getElementById('lingu-widget-root');
      if (container) {
        container.remove();
      }
    };
  }, []);

  return (
    <div>
      <h1>Welcome to My App</h1>
      {/* Your app content */}
    </div>
  );
}

export default App;

Reusable Component

Create a dedicated component for the widget:

tsx
// components/LinguWidget.tsx
import { useEffect } from 'react';

interface LinguWidgetProps {
  apiKey: string;
  autoOpen?: boolean;
  baseURL?: string;
}

// Extend Window interface
declare global {
  interface Window {
    linguConfig?: {
      apiKey: string;
      autoOpen?: boolean;
      baseURL?: string;
    };
    LinguWidget?: any;
  }
}

export function LinguWidget({ apiKey, autoOpen = false, baseURL }: LinguWidgetProps) {
  useEffect(() => {
    // Prevent duplicate initialization
    if (window.LinguWidget) {
      return;
    }

    // Set configuration
    window.linguConfig = {
      apiKey,
      autoOpen,
      ...(baseURL && { baseURL })
    };

    // Create and append script
    const script = document.createElement('script');
    script.src = 'https://widget.uselingu.app/widget.js';
    script.async = true;
    script.id = 'lingu-widget-script';
    document.body.appendChild(script);

    // Cleanup
    return () => {
      const existingScript = document.getElementById('lingu-widget-script');
      if (existingScript) {
        existingScript.remove();
      }
      const container = document.getElementById('lingu-widget-root');
      if (container) {
        container.remove();
      }
      delete window.linguConfig;
      delete window.LinguWidget;
    };
  }, [apiKey, autoOpen, baseURL]);

  return null; // Widget renders itself into the DOM
}

Usage

tsx
// App.tsx
import { LinguWidget } from './components/LinguWidget';

function App() {
  return (
    <div>
      <h1>My React App</h1>
      
      {/* Add at the root level */}
      <LinguWidget 
        apiKey="your-api-key-here"
        autoOpen={false}
      />
    </div>
  );
}

Using Environment Variables

Store your API key in environment variables:

bash
# .env
REACT_APP_LINGU_API_KEY=lingu_abc123def456
tsx
<LinguWidget 
  apiKey={process.env.REACT_APP_LINGU_API_KEY!}
/>

WARNING

For Create React App, environment variables must start with REACT_APP_. For Vite, use VITE_ prefix instead.

Conditional Rendering

Only show the widget on certain pages:

tsx
import { useLocation } from 'react-router-dom';

function App() {
  const location = useLocation();
  
  // Show widget on all pages except /admin
  const showWidget = !location.pathname.startsWith('/admin');

  return (
    <div>
      <Routes>{/* ... */}</Routes>
      
      {showWidget && (
        <LinguWidget apiKey="your-api-key-here" />
      )}
    </div>
  );
}

TypeScript Support

Create type declarations for the global window object:

typescript
// types/lingu.d.ts
declare global {
  interface Window {
    linguConfig?: {
      apiKey: string;
      autoOpen?: boolean;
      baseURL?: string;
    };
    LinguWidget?: {
      new(): {
        destroy(): void;
      };
    };
  }
}

export {};

Best Practices

  1. Load at Root Level: Add the widget component at your app's root level (in App.tsx or layout)

  2. Single Instance: Avoid creating multiple widget instances on the same page

  3. Cleanup: Always clean up when unmounting to prevent memory leaks

  4. Environment Variables: Use environment variables for API keys instead of hardcoding

  5. Lazy Loading: The widget loads asynchronously and won't block your app's initial render

Powered by Lingu