Custom components
A custom component is a renderer, not an action site. It receives typed inputs from the flow, renders your React Native UI, and emits named events. The editor decides what each event does (navigate, set a variable, close the flow, and so on).Register at startup
Register before any flow that uses the component is presented, normally right afterconfigure(...).
Registration shape
What your component receives
Yourcomponent is rendered with CustomComponentRenderProps:
props.inputsholds the resolved input values. Each is aVariableValue(string, number, boolean, or array), so cast to the type you declared.context.emit(eventName, payload?)fires one of your declared output events. The editor’s interaction for that event runs its action chain. Output payloads are validated against theoutputsschema before reaching the chain.context.containerSize/containerConstraintsdescribe the space the flow gave your component, for laying out responsively.
How the flow references it
The editor produces flow JSON that references the component by key and binds each input to a variable ({ "bind": "user.name" }) or a constant ({ "value": true }), and wires each emitted event to an action chain:
Unregister
To remove a registered component (for example on logout), call:Principles
- Custom components are renderers, not action sites. Emit events with
context.emit(...)and let the editor decide what happens next. - Inputs are validated against the declared
inputsschema by the editor when authoring a flow. - Output payloads are schema-validated against the declared
outputsschema before being passed to action chains.
Custom actions
If a flow needs to call native code that the built-in action kinds do not cover (open a native paywall, request a permission, start a purchase), register a custom action handler. The editor then references it by key with acustom action.
params carries any params object the editor attached to the action. context gives you the flow’s variableStore, navigationController, the current flowId / screenId, and isFlowClosed. The editor references the action like this:
FlowPilot.unregisterCustomAction('open_native_paywall').
Action chains run with timeout protection (about 5s per chain, 2s per async action). A custom action that hangs is abandoned so it cannot freeze the flow, and an unregistered
custom action is skipped with a warning, not an error. Keep handlers fast, or kick off long work and return.Common mistakes
- Registering after presenting. Register custom components and actions before the flow that uses them is presented, or the component shows a placeholder and the action is skipped.
- Key mismatch. The
keyyou register must match thecomponentType/actionKeyin the flow exactly (case-sensitive). - Version mismatch. Components match on
key + version. If the flow uses version2, register version2. - Treating a custom component as an action site. Do not call navigation directly from inside the component. Emit an event and let the editor’s interaction handle it, so flow logic stays in the editor.
- Long-running custom actions. A handler that exceeds the per-action timeout is abandoned. Start the work and return, or report progress through a custom component instead.
Troubleshooting
- Component renders a blank placeholder. It was not registered, registered after presenting, or the key/version does not match the flow. Register the exact key and version at startup. Enable
logLevel: 'debug'to see the lookup miss. - An emitted event does nothing. The editor has no interaction wired for that event name, or the event name does not match the declared output. Confirm the
outputskey matches what youemit(...). - A custom action never runs. The handler key does not match the flow’s
actionKey, or it was registered too late. Register before presenting, and check the warning in debug logs.