Skip to content

feat(example): subscribe to form lifecycle events with debug modal#350

Merged
evan-masseau merged 1 commit intofeat/example-appfrom
ecm/example-app/lifecycle-hooks
Apr 22, 2026
Merged

feat(example): subscribe to form lifecycle events with debug modal#350
evan-masseau merged 1 commit intofeat/example-appfrom
ecm/example-app/lifecycle-hooks

Conversation

@evan-masseau
Copy link
Copy Markdown
Contributor

@evan-masseau evan-masseau commented Apr 21, 2026

Description

Part 4 of 4 in the RN example-app overhaul chain for MAGE-464. Adds a live event log for Klaviyo.registerFormLifecycleHandler — the new API introduced in RN SDK 2.4.0 — so integrators have a working reference implementation and a built-in protocol inspector for their QA sessions.

Stacked on #345 (ecm/example-app/4-native). This PR should be rebased onto feat/example-app (or master, whichever is the eventual landing target) once #345 merges; the diff shown here is only the delta on top of that base.

What changed

  • useForms — subscribes to registerFormLifecycleHandler on mount (no toggle needed; SDK only emits while forms are registered). Stores events in a ring-buffer (FIFO, capped at 100) so a long QA session doesn't pin an ever-growing array.
  • FormLifecycleEventsModal (new) — mirrors the GeofencesModal structure. Renders a FlatList with per-event timestamps, formId/formName, event type badge, and buttonLabel/deepLinkUrl for CTA-click events. Keys are a monotonic id assigned at insertion for stable FlatList reconciler reuse across prepends. Detail fields use JSON.stringify so the modal functions as a protocol inspector — buttonLabel: "" renders as "" rather than collapsing (the SDK documents empty-string as a valid value).
  • FormsSection — new ActionButton showing a live count of captured events that opens the modal.

Due Diligence

  • I have tested this on a simulator/emulator or a physical device, on iOS and Android (if applicable).
  • I have added sufficient unit/integration tests of my changes.
  • I have adjusted or added new test cases to team test docs, if applicable.
  • I am confident these changes are implemented with feature parity across iOS and Android (if applicable). (JS-only change; no platform split.)

Release/Versioning Considerations

  • Patch Contains internal changes or backwards-compatible bug fixes.
  • Minor Contains changes to the public API.
  • Major Contains breaking changes.
  • Contains readme or migration guide changes.
  • This is planned work for an upcoming release.

Example app only — no public API changes, no version bump needed.

Changelog / Code Overview

File Change
example/src/hooks/useForms.ts Subscribe to lifecycle handler on mount; maintain ring-buffer event state; return event array + clear fn
example/src/components/FormLifecycleEventsModal.tsx New modal component — chronological event log with type badge, timestamps, and detail inspector
example/src/sections/FormsSection.tsx New ActionButton wiring event count → modal

Test Plan

Here's how it looks
Screenshot 2026-04-21 at 5 06 57 PM
Screenshot 2026-04-21 at 5 06 46 PM

  • iOS: trigger a form show event — confirm it appears in the modal with correct formId, formName, and timestamp
  • iOS: trigger a form dismiss — confirm dismissed event type badge appears
  • iOS: trigger a form CTA click — confirm buttonLabel and deepLinkUrl are rendered (not collapsed), including when buttonLabel is an empty string
  • iOS: generate >100 events — confirm older entries are evicted (ring-buffer, not unbounded growth)
  • Android: repeat the above — same behavior expected (JS-only change)
  • Confirm Clear button resets the list and the count badge on FormsSection goes to 0
  • Confirm app cold-starts cleanly with no forms registered — no crash, event count shows 0

Related Issues/Tickets

Part of MAGE-464

Chained PR series:

  1. theme + components (merged in feat(example): add theme system and reusable UI components #342)
  2. JS layer: permission helpers, hooks, app shell (merged in feat(example): rebuild JS layer with permission helpers, hooks, and app shell #343)
  3. native platform setup — feat(example): native platform setup for Firebase push (iOS + Android) #345
  4. This PR — lifecycle event subscription + debug modal
  5. docs — docs(example): update READMEs for JS-first init and Firebase push setup #346

🤖 Generated with Claude Code

Subscribe to Klaviyo.registerFormLifecycleHandler on mount in useForms so
every shown/dismissed/CTA-click event is console.logged. Retain the event
stream in a ring-buffer (capped at 100 entries, FIFO) in state and expose a
FormLifecycleEventsModal (mirroring the GeofencesModal pattern) that renders
a chronological log with per-event timestamps, formId/formName, and
buttonLabel/deepLinkUrl for CTA-click events. Detail fields rendered via
JSON.stringify so the modal doubles as a protocol inspector — documented
valid empty strings show as "" rather than collapsing into a placeholder.
Event keys are a monotonic id assigned at insertion so FlatList reconciler
reuse is stable across prepends. FormsSection gets an ActionButton showing
the running event count that opens the modal.

Demonstrates the 2.4.0 registerFormLifecycleHandler API; subscribing
unconditionally is safe — the SDK only emits events while forms are
registered.

Part of MAGE-464

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@evan-masseau evan-masseau marked this pull request as ready for review April 21, 2026 21:07
@evan-masseau evan-masseau requested a review from a team as a code owner April 21, 2026 21:07
@klaviyoit klaviyoit requested a review from dan-peluso April 21, 2026 21:07
Base automatically changed from ecm/example-app/4-native to feat/example-app April 21, 2026 22:41
@evan-masseau evan-masseau merged commit 0411236 into feat/example-app Apr 22, 2026
10 checks passed
@evan-masseau evan-masseau deleted the ecm/example-app/lifecycle-hooks branch April 22, 2026 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants