Skip to main content
Learn how to integrate Entri into your React application with proper event handling and state management.

Prerequisites

  • Your applicationId from the Entri dashboard
  • A valid JWT token fetched from your server
  • Basic understanding of React hooks

Installation

npm install entrijs
Import the functions you need:
import { showEntri, close, checkDomain } from 'entrijs';
NPM functions are async - the package automatically loads the Entri SDK when first called.

Quick Start (NPM)

import { useEffect } from 'react';
import { showEntri } from 'entrijs';

function DomainConnect({ applicationId, token }) {
  useEffect(() => {
    const handleClose = (event) => {
      console.log('Entri closed:', event.detail);
    };

    window.addEventListener('onEntriClose', handleClose);
    return () => window.removeEventListener('onEntriClose', handleClose);
  }, []);

  const handleConnect = async () => {
    await showEntri({
      applicationId,
      token,
      dnsRecords: [
        {
          type: 'CNAME',
          host: 'www',
          value: 'your-service.com',
          ttl: 300,
        },
      ],
    });
  };

  return <button onClick={handleConnect}>Connect Domain</button>;
}

Custom Hook (NPM)

// hooks/useEntri.js
import { useState, useEffect, useCallback } from 'react';
import { showEntri, close } from 'entrijs';

export function useEntri() {
  const [isOpen, setIsOpen] = useState(false);
  const [result, setResult] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    const handleSuccess = (event) => {
      setResult(event.detail);
    };

    const handleClose = (event) => {
      setIsOpen(false);

      if (event.detail?.error) {
        setError(event.detail.error);
      }
    };

    window.addEventListener('onSuccess', handleSuccess);
    window.addEventListener('onEntriClose', handleClose);

    return () => {
      window.removeEventListener('onSuccess', handleSuccess);
      window.removeEventListener('onEntriClose', handleClose);
    };
  }, []);

  const openEntri = useCallback(async (config) => {
    setIsOpen(true);
    setError(null);
    setResult(null);

    await showEntri({
      applicationId: config.applicationId,
      token: config.token,
      dnsRecords: config.dnsRecords,
      prefilledDomain: config.prefilledDomain,
      userId: config.userId,
    });
  }, []);

  const closeEntri = useCallback(async () => {
    await close();
  }, []);

  return {
    openEntri,
    closeEntri,
    isOpen,
    result,
    error,
  };
}

With TypeScript (NPM)

The package exports types you can use:
import { 
  showEntri, 
  close,
  type EntriConfig,
  type EntriCloseEventDetail,
  type EntriSuccessEventDetail,
} from 'entrijs';

Using the Hook

Once you have the hook, use it in your components:
// components/DomainSetup.jsx
import { useEntri } from '../hooks/useEntri';

export function DomainSetup({ applicationId, token, userId }) {
  const { openEntri, isOpen, result, error } = useEntri();

  const handleConnect = () => {
    openEntri({
      applicationId,
      token,
      userId,
      dnsRecords: [
        {
          type: 'CNAME',
          host: 'www',
          value: 'your-service.com',
          ttl: 300,
        },
      ],
    });
  };

  if (result?.success) {
    return (
      <div className="success">
        Domain {result.domain} connected successfully!
      </div>
    );
  }

  return (
    <div>
      <button onClick={handleConnect} disabled={isOpen}>
        {isOpen ? 'Connecting...' : 'Connect Domain'}
      </button>

      {error && (
        <p className="error">
          Error: {error.title || 'An error occurred'}
        </p>
      )}
    </div>
  );
}

Event Handling

Entri emits events via window. Set up listeners in useEffect before calling showEntri().
Events work the same way for both NPM and Script Tag installations.

onSuccess

Triggered when the user successfully completes domain setup.
useEffect(() => {
  const handleSuccess = (event) => {
    const { domain, setupType, provider, jobId } = event.detail;

    console.log(`Domain ${domain} configured via ${setupType}`);
    // Store jobId for webhook correlation
  };

  window.addEventListener('onSuccess', handleSuccess);
  return () => window.removeEventListener('onSuccess', handleSuccess);
}, []);

onEntriClose

Triggered when the modal is closed, whether successful or not.
useEffect(() => {
  const handleClose = (event) => {
    const { domain, success, setupType, lastStatus, error } = event.detail;

    if (success) {
      console.log(`${domain} configured successfully`);
    } else if (error) {
      console.log(`Error: ${error.code} - ${error.title}`);
    } else {
      console.log(`User exited at: ${lastStatus}`);
    }
  };

  window.addEventListener('onEntriClose', handleClose);
  return () => window.removeEventListener('onEntriClose', handleClose);
}, []);

onEntriStepChange

Triggered when the user moves between screens. Useful for analytics.
useEffect(() => {
  const handleStepChange = (event) => {
    const { step, domain, provider } = event.detail;
    analytics.track('entri_step', { step, domain, provider });
  };

  window.addEventListener('onEntriStepChange', handleStepChange);
  return () => window.removeEventListener('onEntriStepChange', handleStepChange);
}, []);

onEntriManualSetupDocumentationClick

Triggered when the user clicks the manual setup guide link.
useEffect(() => {
  const handleManualClick = () => {
    openSupportChat();
  };

  window.addEventListener('onEntriManualSetupDocumentationClick', handleManualClick);
  return () => window.removeEventListener('onEntriManualSetupDocumentationClick', handleManualClick);
}, []);

Troubleshooting

Event listeners not firing

Make sure you’re adding listeners before calling showEntri(). In React, use useEffect to set up listeners on mount:
// ✅ Correct - listeners added on mount via useEffect
useEffect(() => {
  window.addEventListener('onEntriClose', handler);
  return () => window.removeEventListener('onEntriClose', handler);
}, []);

// ❌ Wrong - listener added after showEntri
const handleClick = () => {
  showEntri(config); // or window.entri.showEntri(config)
  window.addEventListener('onEntriClose', handler); // Too late!
};

Stale state in event handlers

React’s closures can capture stale state. Use refs or functional updates:
// ✅ Use functional update to avoid stale state
setResult(prevResult => ({
  ...prevResult,
  ...event.detail
}));

// ✅ Or use a ref for values needed in event handlers
const configRef = useRef(config);
useEffect(() => {
  configRef.current = config;
}, [config]);

Multiple event handlers firing

Ensure you clean up listeners when the component unmounts:
useEffect(() => {
  const handler = (event) => { /* ... */ };

  window.addEventListener('onEntriClose', handler);

  return () => {
    window.removeEventListener('onEntriClose', handler);
  };
}, []);

Next Steps