@nexbasira/react
Wrapper React attorno a @nexbasira/embed. Due superfici — un componente drop-in <NexBasiraSession> per il caso comune, più un hook useNexBasiraSession() per layout personalizzati.
Installazione
npm install @nexbasira/react @nexbasira/embed react react e @nexbasira/embed sono peer dependency — non sono incluse in questo pacchetto.
Componente
import { NexBasiraSession } from "@nexbasira/react";
function InspectionPage({ joinUrl }: { joinUrl: string }) {
return (
<NexBasiraSession
sessionUrl={joinUrl}
height="720px"
onSessionComplete={(id) => navigate(`/inspections/${id}`)}
/>
);
} sessionUrl è la URL monouso che il tuo backend riceve da sessions.invite() sull'SDK Node / Python. Il componente monta l'iframe al primo render e lo distrugge in modo pulito allo smontaggio.
Accesso imperativo tramite ref
Usa un ref quando i controlli lato campo stanno fuori dall'iframe (toolbar sopra il componente, trigger di modale, ecc.):
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} />
</>
);
} Variante hook
Quando il <div> wrapper non si adatta al tuo layout — poniamo che tu voglia l'iframe in un contenitore flex con una sidebar — usa l'hook + collega il ref restituito al tuo elemento host:
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>
);
} Le callback del ciclo di vita restano fresche tra i render
Il widget embed viene creato una volta per sessionUrl. Per assicurarti che le tue callback vedano sempre la closure più recente (che cattura lo stato più recente), il wrapper le memorizza internamente in un useRef e le rilegge a ogni evento. Puoi passare arrow function inline in sicurezza:
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);
}}
/>
);
} Quando viene ricostruito l'iframe?
Solo quando sessionUrl cambia. Ogni altra prop (callback, width, height, expectedOrigin) si applica in loco senza rimontare. Questo significa che cambiare una callback o ridimensionare l'host non riavvia la sessione live — utile quando la tua app fa re-render di frequente.
Props
| Prop | Tipo | Note |
|---|---|---|
sessionUrl | string | Obbligatorio. Generata dal tuo backend. |
width / height | string | Dimensioni CSS. Default 100% / 600px. |
expectedOrigin | string | Sovrascrive l'origin dell'iframe se ospiti su un dominio personalizzato. |
className | string | Applicato al div wrapper. |
style | CSSProperties | Applicato al div wrapper. |
on* callbacks | function | Stessa superficie di @nexbasira/embed — vedi quella pagina. |
Handle tipizzato
import type { NexBasiraSessionHandle } from "@nexbasira/react";
const ref = useRef<NexBasiraSessionHandle>(null);
// ref.current has typed methods: requestSnapshot(), openWhiteboard(), etc. Prossimi passi
- @nexbasira/embed — widget sottostante
- @nexbasira/node — genera la
sessionUrlnel tuo backend - Sorgente su GitHub