LIVE · AUDIT-KJEDE · EU-VERTET
SYSTEM · 99,99 % OPPETID
v 1.0 ↗ LAGET I EU

@nexbasira/react

React-wrapper rundt @nexbasira/embed. To flater — en plug-and-play <NexBasiraSession>-komponent for det vanlige tilfellet, pluss en useNexBasiraSession()-hook for egendefinerte layouter.

Installasjon

npm install @nexbasira/react @nexbasira/embed react

react og @nexbasira/embed er peer-avhengigheter — de bundles ikke med denne pakken.

Komponent

import { NexBasiraSession } from "@nexbasira/react";

function InspectionPage({ joinUrl }: { joinUrl: string }) {
  return (
    <NexBasiraSession
      sessionUrl={joinUrl}
      height="720px"
      onSessionComplete={(id) => navigate(`/inspections/${id}`)}
    />
  );
}

sessionUrl er engangs-URL-en backend-en din får tilbake fra sessions.invite() på Node- / Python-SDK-en. Komponenten monterer iframe-en ved første render og rydder den ryddig bort ved unmount.

Imperativ tilgang via ref

Bruk en ref når feltside-kontrollene ligger utenfor iframe-en (verktøylinje over komponenten, modal-trigger, osv.):

import { useRef } from "react";
import { NexBasiraSession, type NexBasiraSessionHandle } from "@nexbasira/react";

function Toolbar({ joinUrl }: { joinUrl: string }) {
  const session = useRef<NexBasiraSessionHandle>(null);
  return (
    <>
      <button onClick={() => session.current?.requestSnapshot()}>Capture</button>
      <button onClick={() => session.current?.openWhiteboard()}>Whiteboard</button>
      <button onClick={() => session.current?.endSession()}>End</button>
      <NexBasiraSession ref={session} sessionUrl={joinUrl} />
    </>
  );
}

Hook-variant

Når wrapper-<div>-en ikke passer layouten din — si at du vil ha iframe-en i en flex-container med et sidefelt — bruk hook-en og fest den returnerte ref-en til ditt eget vertselement:

import { useNexBasiraSession } from "@nexbasira/react";

function CustomLayout({ joinUrl }: { joinUrl: string }) {
  const [containerRef, widget] = useNexBasiraSession({
    sessionUrl: joinUrl,
    onSessionComplete: (id) => navigate(`/inspections/${id}`),
  });

  return (
    <div className="grid grid-cols-[1fr_240px] gap-4">
      <div ref={containerRef} style={{ minHeight: 600 }} />
      <aside>
        <button onClick={() => widget.current?.requestSnapshot()}>Snap</button>
      </aside>
    </div>
  );
}

Livssyklus-callbacks holder seg ferske på tvers av renders

Embed-widgeten opprettes én gang per sessionUrl. For å sikre at callbacks-ene dine alltid ser den nyeste closuren (som fanger den nyeste tilstanden), lagrer wrapperen dem internt i en useRef og leser dem på nytt ved hver hendelse. Du kan trygt sende inline pilfunksjoner:

function Page() {
  const [count, setCount] = useState(0);
  return (
    <NexBasiraSession
      sessionUrl={joinUrl}
      onEvidenceAdded={() => {
        // 'count' is always the latest value, not the value at mount
        setCount(count + 1);
      }}
    />
  );
}

Når bygges iframe-en opp på nytt?

Bare når sessionUrl endres. Alle andre props (callbacks, width, height, expectedOrigin) brukes på stedet uten remontering. Det betyr at det å endre en callback eller endre størrelse på verten ikke starter den aktive økten på nytt — nyttig når appen din re-rendrer ofte.

Props

PropTypeMerknader
sessionUrlstringPåkrevd. Generert av backend-en din.
width / heightstringCSS-størrelser. Standard 100% / 600px.
expectedOriginstringOverstyr iframe-origin hvis du hoster på et eget domene.
classNamestringBrukes på wrapper-div-en.
styleCSSPropertiesBrukes på wrapper-div-en.
on* callbacksfunctionSamme flate som @nexbasira/embed — se den siden.

Typet håndtak

import type { NexBasiraSessionHandle } from "@nexbasira/react";

const ref = useRef<NexBasiraSessionHandle>(null);
// ref.current has typed methods: requestSnapshot(), openWhiteboard(), etc.

Hva nå