Skip to content

experiment(react-web-sdk): undefined SDK on server#346

Draft
David Nalchevanidze (nalchevanidze) wants to merge 3 commits into
fix-ssrfrom
experiment/undefined-sdk-path
Draft

experiment(react-web-sdk): undefined SDK on server#346
David Nalchevanidze (nalchevanidze) wants to merge 3 commits into
fix-ssrfrom
experiment/undefined-sdk-path

Conversation

@nalchevanidze

@nalchevanidze David Nalchevanidze (nalchevanidze) commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

What this shows

This branch demonstrates what it would cost to return `undefined` from `useOptimization()` instead of the current `SSR_STUB` approach. It builds on top of `fix-ssr`, so all the SSR implementation work is included — you can see how the undefined path interacts with the actual SSR rendering.

Changes

`useOptimization.ts`

Returns `OptimizationSdk | undefined` — `undefined` before the SDK is ready (SSR and first client render).

All dependent hooks (7 files)

Each hook that consumed `useOptimization()` now needs explicit null guards:

  • `useOptimizationState.ts` — each state hook: `sdk ? sdk.states.X : nullObs()`. Note `canOptimize` needs `nullObs(false)` (boolean), others need `nullObs(undefined)`.
  • `useOptimizationActions.ts` — public API widens: `identify/page/screen/track` now return `Promise<EventEmissionResult | undefined>`. Every method needs an `if (sdk)` or ternary guard.
  • `useEntryResolver.ts` — each resolver: `sdk ? sdk.resolveOptimizedEntry(...) : { entry }` fallback.
  • `useMergeTagResolver.ts` — `sdk ? sdk.getMergeTagValue(...) : undefined`.
  • `useAutoPageEmitter.ts` — `if (!sdk) return` guard in effect.

Callers: package layer

  • `dev/app/App.tsx` — calls `useOptimization()` and passes `sdk` directly to child sections. Requires `if (!sdk) return null` early-exit at the component root.
  • `OptimizationProvider.onStatesReady.test.tsx` — test probes using `useOptimization().states.X` must become `useOptimization()?.states.X`.

Callers: nextjs-sdk_ssr implementation

  • `CustomViewTracker.tsx` — effect calling `sdk.trackView()` needs `if (!sdk) return` guard.
  • `ControlPanel.tsx` — onClick handler calling `sdk.trackView()` needs optional chaining `sdk?.trackView()`.
  • `hooks.ts` — `useControlPanel` already uses `useOptimizationContext()` for direct sdk access (bypasses the issue), but returns `sdk` to callers who must then guard.

Verdict

The undefined path distributes the SSR_STUB cost outward: instead of one central stub that makes the SDK always non-null, every hook and every direct consumer of `useOptimization()` must handle `undefined` explicitly. The API surface (`UseOptimizationActionsResult`) widens, and components that receive the SDK as a prop would also need to accept `undefined`.

The SSR_STUB approach keeps the contract simple: hooks always get a callable SDK, and the stub's no-ops are safe because real SDK calls happen in effects (after `useLayoutEffect` has set the real SDK). This branch shows the alternative is real but costly — every new direct caller of `useOptimization()` would need to know about and handle the undefined window.

Demonstrates the cost of removing the stub pattern. All hooks that consumed
useOptimization() now require explicit sdk guards at every call site, and
callers that received the sdk directly (dev/App.tsx, onStatesReady tests)
must handle undefined — surfacing the full blast radius of this change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Dev app uses early-return guard (if (!sdk) return null) — the pattern
every consumer component would need to adopt. Test probes use optional
chaining (?.states) to handle the undefined path. These fixups show the
propagation cost at concrete call sites.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Shows how the SSR implementation's direct sdk usage sites must also be
updated: effect-based calls need if (!sdk) guards, event handler calls
need optional chaining.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@nalchevanidze David Nalchevanidze (nalchevanidze) marked this pull request as draft July 1, 2026 11:39
@nalchevanidze David Nalchevanidze (nalchevanidze) changed the title experiment: cost of returning undefined from useOptimization experiment(react-web-sdk): undefined from useOptimization Jul 1, 2026
@nalchevanidze David Nalchevanidze (nalchevanidze) changed the title experiment(react-web-sdk): undefined from useOptimization experiment(react-web-sdk): undefined SDK Jul 1, 2026
@nalchevanidze David Nalchevanidze (nalchevanidze) changed the title experiment(react-web-sdk): undefined SDK experiment(react-web-sdk): undefined SDK on server Jul 1, 2026
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.

1 participant