Skip to content

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.

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.