React wrapper
@forms-engine/react wraps the web component in an idiomatic React
component: attributes become props, events become callbacks. It’s a thin
layer — there is one renderer, and this is sugar over it.
import { FormsEngine } from '@forms-engine/react';
export function Questionnaire() { return ( <FormsEngine publicId="q_a1b2c3d4e5" apiBase="https://forms.your-domain.com" externalRef={user.id} onCompleted={({ responseId }) => console.log('done', responseId)} onError={(detail) => console.error(detail)} /> );}Importing the package registers the <forms-engine> custom element as a
side effect. That touches browser globals at import time, so in SSR
frameworks (Next.js and friends) load it client-side only — mark the
module "use client" or dynamic-import it with SSR disabled.
| Prop | Type | Purpose |
|---|---|---|
publicId |
string (required) |
→ public-id |
apiBase |
string (required) |
→ api-base |
externalRef |
string |
→ external-ref |
className, style |
usual React types | Applied to the <forms-engine> element |
onLoaded |
(detail) => void |
← fe-loaded |
onScreenChanged |
(detail) => void |
← fe-screen-changed |
onCompleted |
(detail) => void |
← fe-completed |
onResumed |
(detail) => void |
← fe-resumed |
onAlreadySubmitted |
(detail) => void |
← fe-already-submitted |
onError |
(detail) => void |
← fe-error |
Each callback receives the event’s detail payload directly — shapes as
documented in Events. The component is entirely
uncontrolled: all form state lives inside the web component.
Peer dependency: React 18 or newer.
What the wrapper doesn’t expose
Section titled “What the wrapper doesn’t expose”persist-session, completion-redirect, and labels have no props in
the current wrapper. If you need them in a React app, use the web
component directly — it’s the same renderer:
import '@forms-engine/renderer';
<forms-engine public-id="q_a1b2c3d4e5" api-base="https://forms.your-domain.com" completion-redirect="https://your-app.com/thanks" labels='{"finish":"Enviar"}'/>React 19 passes unknown attributes through to custom elements, so this
works in JSX as written (attach event listeners with a ref). One typing
note: the onError detail is typed as { message, cause? }, but
component-detected errors carry { code, message } instead — check
detail.code before assuming a cause.