본문으로 건너뛰기

클라이언트 라이브러리

프레임워크 어댑터

React 래퍼

TypeScript SDK 위에 얹는 프로바이더 하나와 훅 두 개입니다. 페이지당 클라이언트를 하나만 설치하므로 React 엄격 모드에서도 이벤트가 중복되지 않습니다.

배포 위치

@prodantix/react on npm. It wraps @prodantix/sdk, so install both.

설치

Bash
bun add @prodantix/sdk @prodantix/react
ExportWhat it is
ProdantixProviderCreates the client once per page and provides it
useProdantixThe client for the page, or null
useMessengerA handle that opens and closes the widget, or null
prodantixConfigThe config when both key and host are present, else null
skipReasonWhy this mount will send nothing, or null
resetProdantixForTestClears the once-per-page install, for tests

프로바이더

ProdantixProvider는 루트 가까이에 한 번만 마운트하세요. 첫 마운트에서 웹 클라이언트를 만들고 이후에는 그것을 재사용합니다. 두 번째를 만들면 History API에 패치가 두 번 적용되어 자동 수집된 이벤트가 모두 두 배가 되기 때문입니다.

TypeScript
import { ProdantixProvider } from '@prodantix/react';

export const Providers = ({ children }: { children: ReactNode }) => (
  <ProdantixProvider
    options={{
      apiKey: process.env.NEXT_PUBLIC_PRODANTIX_KEY,
      host: 'https://eu.api.prodantix.com',
      messengerHost: 'https://eu.edge.prodantix.com',
    }}
  >
    {children}
  </ProdantixProvider>
);
메신저는 messengerHost를 넘기고 프로젝트가 콘솔에서 이를 켜 두었을 때만 나타납니다. 구성도 캐시도 없으면 아무것도 렌더링하지 않습니다. 기본 런처는 고객 페이지에 칠해 놓은 추측일 뿐이기 때문입니다.

로그인한 사람을 지정하기

person은 누가 로그인해 있는지를 호출이 아니라 prop으로 프로바이더에 알려 줍니다. 그래서 로그인과 로그아웃이 있는 그대로의 값으로 클라이언트에 닿습니다. 상태는 셋이고 각각 다른 말을 합니다. undefined는 이 화면이 아직 모른다는 뜻이며, 인증이 아직 하이드레이션 중이기 때문에 프로바이더는 아무것도 하지 않습니다. 값이 있으면 식별합니다. 프로바이더는 첫 값에서 identify를 부르고 distinctId가 바뀔 때마다 다시 부르며, SDK 자신의 특성인 아바타, 이메일, 이름, 전화를 함께 보냅니다. null은 화면이 세션을 확인했고 아무도 없었다는 뜻입니다. 프로바이더는 클라이언트가 아직 식별된 상태일 때에만 리셋하며, 그러면 익명 id가 회전하여 그 브라우저의 다음 방문자가 방금 로그아웃한 사람이 되지 않습니다. 로그아웃이 하드 내비게이션이라 값에서 null로 가는 전환이 결코 그려지지 않는 곳에서도 로그아웃을 지켜 주는 것이 바로 이 규칙입니다. null이 결코 로딩을 뜻해서는 안 되는 이유이기도 합니다. 로그인한 사람이 페이지를 새로 고치면 인증이 하이드레이션되기 전에 리셋되어 버립니다. 세션을 전혀 확인하지 않는 마운트, 랜딩 페이지나 문서 페이지는 undefined를 넘기고, prop이 없으면 이미 undefined로 읽힙니다.

TypeScript
import { ProdantixProvider } from '@prodantix/react';

export const Providers = ({ children }: { children: ReactNode }) => {
  const { session, status } = useSession();

  // undefined while auth hydrates, null once it has resolved to nobody,
  // the subject once it has resolved to someone.
  const person = status === 'loading' ? undefined : session ? { distinctId: session.sub } : null;

  return (
    <ProdantixProvider
      options={{
        apiKey: process.env.NEXT_PUBLIC_PRODANTIX_KEY,
        host: 'https://eu.api.prodantix.com',
        person,
      }}
    >
      {children}
    </ProdantixProvider>
  );
};

훅

useProdantix는 해당 페이지의 클라이언트를 반환하며, 서버에서, 이펙트가 실행되기 전, 그리고 프로바이더 바깥에서는 null입니다. useMessenger는 위젯을 열고 닫는 핸들을 반환하고, 프로젝트 구성을 읽어 활성으로 확인되기 전까지는 null로 남습니다.

TypeScript
import { useMessenger, useProdantix } from '@prodantix/react';

export const HelpButton = () => {
  const prodantix = useProdantix();
  const messenger = useMessenger();

  // Both are null until the provider effect has run, so neither is assumed.
  return (
    <button
      onClick={() => {
        prodantix?.capture('help.opened');
        messenger?.open();
      }}
      type="button"
    >
      Get help
    </button>
  );
};

아무것도 보내지 않을 때

Prodantix를 꺼 둔 상태로도 앱은 똑같이 배포되므로, 키나 호스트가 없는 것은 오류가 아닙니다. prodantixConfig는 두 값이 모두 있는지 알려주고, skipReason은 조용히 반환하는 대신 이 마운트가 아무것도 보내지 않는 이유를 한 줄로 말해 줍니다.

TypeScript
import { prodantixConfig, skipReason } from '@prodantix/react';

const env = {
  host: process.env.NEXT_PUBLIC_PRODANTIX_HOST,
  key: process.env.NEXT_PUBLIC_PRODANTIX_KEY,
};

// null when either value is missing: the app runs with Prodantix switched off.
if (prodantixConfig(env) === null) {
  console.warn(skipReason(env, null));
}