Repository navigation
Upgrade the example app to Expo SDK 57 - #293
Merged
majkpal merged 3 commits intoAug 31, 2026
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Upgrades the examples/react-native/WhipWhepDemo Expo app from SDK 54 to SDK 57 and aligns the workspace tooling/types with the stricter TypeScript / module settings brought in by newer Expo module tooling.
Changes:
- Bump the example app to Expo SDK 57 (RN 0.86 / React 19.2) and update related Expo/RN dependencies.
- Adjust
react-native-clientTS surface (type-only imports/exports and aconnectsignature fix) for stricter TS settings. - Update the iOS config plugin deployment-target logic to avoid downgrading Expo’s default deployment target.
Reviewed changes
Copilot reviewed 18 out of 19 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/react-native-client/src/ReactNativeMobileWhipClientViewModule.ts | Type/import updates and native module typing change. |
| packages/react-native-client/src/ReactNativeMobileWhipClientView.tsx | Convert several imports to type-only. |
| packages/react-native-client/src/ReactNativeMobileWhepClientView.tsx | Convert several imports to type-only. |
| packages/react-native-client/src/ReactNativeMobileWhepClient.types.ts | Fix connect parameter naming to avoid any. |
| packages/react-native-client/src/index.ts | Split value export (VideoParameters) from type exports under stricter TS. |
| packages/react-native-client/src/hooks/useEventState.ts | Use type-only import for payload typings. |
| packages/react-native-client/src/hooks/useEvent.ts | Use type-only import for payload typings. |
| packages/react-native-client/src/hooks/useConnectionState.ts | Use type-only imports for peer-connection state types. |
| packages/react-native-client/src/hooks/eventPayloadValidator.ts | Use type-only import for payload typings. |
| packages/react-native-client/plugin/src/withWhipWhepIos.ts | Avoid writing a low deployment target unless explicitly set / needed. |
| packages/react-native-client/package.json | Update dev tooling deps (expo-module-scripts, typedoc, @types/react). |
| package.json | Update repo-wide linting/tooling dependency versions. |
| examples/react-native/WhipWhepDemo/package.json | Upgrade example app dependency matrix to SDK 57 + Jest 30 tooling. |
| examples/react-native/WhipWhepDemo/hooks/useThemeColor.ts | Route theme selection through local useColorScheme wrapper. |
| examples/react-native/WhipWhepDemo/hooks/useColorScheme.ts | New wrapper to collapse RN 0.86 useColorScheme() into app themes. |
| examples/react-native/WhipWhepDemo/app/(tabs)/_layout.tsx | Consume the new useColorScheme wrapper for safe palette indexing. |
| examples/react-native/WhipWhepDemo/app.json | Remove iOS deployment target pin; add required SDK 57 config plugins. |
| examples/react-native/WhipWhepDemo/.eslintrc | Remove trailing comma for strict JSON parsing. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
majkpal
added a commit
that referenced
this pull request
Aug 31, 2026
`yarn lint:check` runs `swift-format lint -s` for the `ios-client` workspace, and under `-s` (strict) `TrailingWhitespace` is an error rather than a warning. 26 lines across four files trip it, so the `all_packages_lint` job fails. **This is on `main`, not introduced by any open PR** — it currently fails CI on every one of them. Reproduced on a clean `origin/main` checkout: 26 errors, exactly the set CI reports. ``` Sources/ios-client/Capturers/BroadcastScreenShareCapturer.swift:100:1: error: [TrailingWhitespace] … Sources/ios-client/ClientBase.swift:111:1: error: [TrailingWhitespace] … … 24 more, in ClientBase.swift, WhepClient.swift and WhipClient.swift ``` The fix is just the workspace's own `yarn lint` (`swift-format format -i`) — no hand edits. ## Why this is safe - `git diff -w` on the commit is **empty**: nothing but whitespace changed. - Every one of the 26 removed lines was blank apart from its trailing spaces, so nothing touches a string literal or any token. Compilation cannot be affected. - After it, `swift-format lint -r -s ./Sources --configuration swift-format-config.json` reports 0 errors. ## Why `examples/ios` was never affected The `ios_lint` workflow runs `swift-format format -i` *before* `swift-format lint`, so it silently fixes the tree in the runner and then lints the fixed copy. Only `all_packages_lint`, which goes through `yarn lint:check`, actually enforces this — and it only covers `packages/ios-client`. Worth considering separately: having `ios_lint` format-then-lint means it can never fail on formatting, which is presumably not the intent. ## Merge order Kept standalone and based directly on `main` so it can go in ahead of #291, #292 and #293 — all three go green once they pick it up. Happy to cherry-pick it into #291 instead if you would rather not have a fourth PR. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Moves examples/react-native/WhipWhepDemo from SDK 54 to SDK 57, which is what the four Dependabot PRs left open on software-mansion#292 were really asking for: RN 0.81.4 -> 0.86.3, React 19.1 -> 19.2.3, reanimated 4.1 -> 4.5.1 and worklets 0.5.1 -> 0.10.1 are all just the SDK 57 matrix. Beyond `expo install --fix`, the upgrade needed: - expo-module-scripts ~4.0.5 -> ~56.0.3. Not optional: 4.0.5 depends on babel-preset-expo ~12, which hoists to the workspace root and shadows the copy expo@57 ships, so Metro fails to bundle react-native itself ("Unable to determine event arguments for onModeChange"). 56.0.3 drops that dependency. - babel-preset-expo added to the example's devDependencies. Once nothing hoists it to the root, @expo/metro-config can no longer resolve it from the workspace root. - The tsconfig that expo-module-scripts 56 brings turns on verbatimModuleSyntax, isolatedModules and strict, so type-only imports and re-exports in packages/react-native-client are marked as such. The emitted build/ output becomes ESM, which is exactly how Expo's own SDK 57 modules (expo-camera, expo-web-browser) ship - `main` pointing at ESM with no "type": "module" - and the config plugin under plugin/build stays CommonJS, which is what app.plugin.js needs. - Two real type errors that the looser old config hid: `connect: (ConnectOptions) => Promise<void>` named its parameter after its type and silently took `any`, and the WHIP module type never declared `whipPeerConnectionState` even though useWhipConnectionState reads it. - The iOS config plugin wrote `ios.deploymentTarget` unconditionally, so it downgraded the Expo template's own default (16.4 on SDK 57) to this SDK's 15.1 minimum and left CocoaPods unable to resolve the Expo pod. It now only raises an existing lower value, and honours an explicit `iphoneDeploymentTarget` as before. The example's app.json no longer pins 15.1 for the same reason. - RN 0.86 widened `useColorScheme()` to include 'unspecified' and made it non-nullable, so the example's hook collapses it to the two themes it actually defines. Verified: yarn build, yarn tsc, yarn lint:check, yarn docs, expo export, expo prebuild --clean, an iOS simulator build of the Expo example and ./gradlew :app:assembleDebug for Android - all green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Type both `wh{i,e}pPeerConnectionState` as optional. Neither is backed
by a native `Property` on either platform, so they read back as
`undefined`, which `PeerConnectionState | null` did not allow. Neither
is re-exported from `src/index.ts`, so this is internal to the module
files; the connection-state hooks already fall back to "unknown".
- Floor `expo` at the version this was verified against (`^57.0.18`)
rather than `^57.0.0`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
majkpal
force-pushed
the
chore/upgrade-expo-sdk-57
branch
from
August 31, 2026 09:17
bd66763 to
517335b
Compare
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Moves
examples/react-native/WhipWhepDemofrom Expo SDK 54 to SDK 57. This is what Dependabot #284–#287 were really asking for — RN 0.81.4 → 0.86.3, React 19.1 → 19.2.3, reanimated 4.1 → 4.5.1 and worklets 0.5.1 → 0.10.1 are all just the SDK 57 matrix — and it closes out the "left behind" list on #292.What
expo install --fixdidexpo@^57, and with itexpo-audio,expo-camera,expo-constants,expo-font,expo-keep-awake,expo-linking,expo-router,expo-splash-screen,expo-status-bar,expo-system-ui,expo-web-browser(all now on unified~57.x), plusreact/react-dom19.2.3,react-native0.86.3,react-native-gesture-handler~2.32,react-native-reanimated4.5.1,react-native-safe-area-context~5.7,react-native-screens~4.26,react-native-worklets0.10.1,@types/react~19.2.4,typescript~6.0.3,jest-expo~57.0.5.app.jsongained theexpo-splash-screenandexpo-status-barconfig plugins that SDK 57 requires. Alongside it:jest30,@types/jest30 (jest-expo@57needs them),react-test-renderer19.2.3 to match React 19, and@react-native/eslint-config^0.86.3.What the upgrade actually needed on top
Each of these was a hard failure, not a tidy-up:
expo-module-scripts~4.0.5 → ~56.0.3. Not optional. 4.0.5 depends onbabel-preset-expo ~12, which hoists to the workspace root and shadows the copyexpo@57ships, so Metro fails bundling react-native itself:Unable to determine event arguments for "onModeChange". 56.0.3 dropped that dependency.babel-preset-expoadded to the example's devDependencies. Once nothing hoists it to the root,@expo/metro-configcan't resolve it from there:Cannot find module 'babel-preset-expo'.packages/react-native-client. The tsconfigexpo-module-scripts56 brings turns onverbatimModuleSyntax,isolatedModulesandstrict. 28 of the 30 resulting errors are mechanical (import type/export type).ios.deploymentTargetunconditionally, downgrading the Expo template's own default (16.4 on SDK 57) to this SDK's 15.1 minimum, which left CocoaPods unable to resolve the Expo pod. It now only raises an existing lower value, and still honours an explicitiphoneDeploymentTarget. The example'sapp.jsonno longer pins 15.1 for the same reason.useColorScheme(). RN 0.86 widened it to include'unspecified'and made it non-nullable, soColors[colorScheme ?? 'light']no longer type-checks. The example's own hook now collapses it to the two themes it defines.Two real bugs the stricter config surfaced
Both pre-existing, both in the published SDK's types:
connect: (ConnectOptions) => Promise<void>onWhepClientViewRefnamed its parameter after its type, so the argument was silentlyany. Nowconnect: (options: ConnectOptions) => Promise<void>.RNMobileWhipClientViewModulenever declaredwhipPeerConnectionState, even thoughuseWhipConnectionStatereads it. Declared now, mirroring the WHEP module.Worth a follow-up: neither
whipPeerConnectionStatenorwhepPeerConnectionStateactually exists as a nativePropertyon either platform — onlycamerasdoes. Both hooks fall back to"unknown"via??and then track the change events, so behaviour is unaffected, but the exportedwhepPeerConnectionStateconst is permanentlyundefined. Out of scope here; left as-is rather than changing native behaviour in an upgrade PR.On the ESM output
build/now emits ESM rather than CommonJS. That matches how Expo's own SDK 57 modules ship —expo-cameraandexpo-web-browserboth havemainpointing at ESM with no"type": "module"— and Metro handles it. The config plugin underplugin/buildstays CommonJS, which is whatapp.plugin.jsrequires. This resolves the concern I raised on #292.Testing
yarn build✅yarn tsc✅yarn lint:check✅ (only the gitignored, generatedexpo-env.d.ts)yarn docs✅ (same 4 pre-existing typedoc warnings)npx expo export --platform ios✅npx expo prebuild --clean✅ includingpod installxcodebuild -workspace WhipWhepDemo.xcworkspace -scheme WhipWhepDemo -destination 'platform=iOS Simulator,name=iPhone 17'→** BUILD SUCCEEDED **./gradlew :app:assembleDebug(JDK 17) →BUILD SUCCESSFULNot exercised: runtime behaviour against a live WHIP/WHEP server, and the iOS broadcast-extension screen-share path on a physical device. Both native example apps (
examples/ios,examples/android) are untouched by this PR.🤖 Generated with Claude Code