LIVE · AUDIT-KÆDE · EU-HOSTET
SYSTEM · 99,99 % OPPETID
v 1.0 ↗ FREMSTILLET I EU

@nexbasira/react

React-wrapper omkring @nexbasira/embed. To flader — en drop-in-<NexBasiraSession>-komponent til det almindelige tilfælde plus en useNexBasiraSession()-hook til brugerdefinerede layouts.

Installation

npm install @nexbasira/react @nexbasira/embed react

react og @nexbasira/embed er peer-dependencies — de er ikke bundlet med denne pakke.

Komponent

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

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

sessionUrl er den engangs-URL, din backend får tilbage fra sessions.invite() på Node- / Python-SDK'et. Komponenten monterer iframe'en ved første render og fjerner den rent ved unmount.

Imperativ adgang via ref

Brug en ref, når feltsidens kontroller ligger uden for iframe'en (værktøjslinje 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 til dit layout — sig, du vil have iframe'en i en flex-container med en sidebar — brug hooken + tilknyt den returnerede ref til dit eget host-element:

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>
  );
}

Lifecycle-callbacks forbliver friske på tværs af renders

Embed-widget'en oprettes én gang pr. sessionUrl. For at sikre, at dine callbacks altid ser den nyeste closure (der lukker over den nyeste state), gemmer wrapperen dem internt i en useRef og genlæser ved hver event. Du kan trygt sende inline arrow-funktioner:

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);
      }}
    />
  );
}

Hvornår genopbygges iframe'en?

Kun når sessionUrl ændres. Alle andre props (callbacks, width, height, expectedOrigin) anvendes in-place uden remontering. Det betyder, at en ændring af et callback eller ændring af host-størrelsen ikke genstarter live-sessionen — nyttigt når din app re-renderer ofte.

Props

PropTypeNoter
sessionUrlstringPåkrævet. Genereres af din backend.
width / heightstringCSS-størrelser. Standard 100% / 600px.
expectedOriginstringTilsidesæt iframe-origin ved hosting på et brugerdefineret domæne.
classNamestringAnvendes på wrapper-div'en.
styleCSSPropertiesAnvendes på wrapper-div'en.
on* callbacksfunctionSamme flade som @nexbasira/embed — se den side.

Typet handle

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

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

Hvad er det næste