fix(interop): unwrap CJS default exports (react-player, @emoji-mart/react)#3199
Merged
Conversation
react-player ships as CommonJS with the component on `exports.default`.
Some bundler/interop setups (e.g. Vite serving our built ESM as a linked
workspace dependency) hand back the module namespace `{ default }` instead
of the component, causing React to throw "Element type is invalid ... got:
object". Unwrap the default defensively so VideoPlayer renders regardless
of how the consumer's bundler handles interop.
|
Size Change: +69 B (+0.01%) Total Size: 651 kB π¦ View Changed
βΉοΈ View Unchanged
|
MartinCupela
approved these changes
May 27, 2026
Codecov Reportβ
All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3199 +/- ##
==========================================
- Coverage 83.73% 83.71% -0.03%
==========================================
Files 435 435
Lines 13127 13129 +2
Branches 4249 4251 +2
==========================================
- Hits 10992 10991 -1
- Misses 2135 2138 +3 β View full report in Codecov by Sentry. π New features to boost your workflow:
|
Same interop hazard as the react-player fix: @emoji-mart/react ships as
CommonJS with the component on `exports.default`. Under spec-strict ESM
interop (Vite 8 / Rolldown, native Node ESM) the default import resolves to
the module namespace `{ default }` instead of the component, causing React
to throw "Element type is invalid ... got: object" when rendering <Picker>.
Unwrap the default defensively.
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.
π― Goal
Fix a runtime crash β
Uncaught Error: Element type is invalid: expected a string ... but got: objectβ when components backed by externalized CommonJS dependencies are rendered under spec-strict ESMβCJS interop. Two components are affected:VideoPlayerβreact-playerEmojiPickerβ@emoji-mart/reactThis first surfaced in the Vite example, which consumes the SDK's built ESM (
dist/es) as a linked workspace dependency. Vite 8 swapped its dependency optimizer from esbuild to Rolldown. esbuild honored the Babel__esModulemarker and unwrapped.default; Rolldown follows spec-strict interop where a CJS module's ESM default export ismodule.exportsitself. Soimport ReactPlayer from 'react-player'(andimport Picker from '@emoji-mart/react') now resolve to the module namespace{ default, __esModule }β an object β and rendering it throws. Native Node ESM behaves identically, so this was never spec-portable; it only worked under bundlers that honored__esModule.π Implementation details
Both packages ship as CJS with the real export on
exports.default. We unwrap the interop default defensively at each import site:When the bundler already provides the component (the normal case β esbuild, webpack, pre-Vite-8),
.defaultisundefinedand it falls back to the import unchanged. So this is a no-op for existing consumers and resolves thegot: objectcrash only where the namespace leaks through.Audit. Every default-imported externalized dependency in
src/was checked against native-Node-ESM (β‘ Rolldown strict) interop. Onlyreact-playerand@emoji-mart/reactexhibit the hazard signature (object default carrying{ __esModule, default }). All others are safe:module.exports:clsx,dayjs+ alldayjs/plugin/*,lodash.debounce/mergewith/throttle/uniqby,emoji-regex,fix-webm-duration,react-fast-compare,moment-timezonereact-markdown,remark-gfmreact(namespace),i18next(instance),react-textarea-autosize(forwardRef)Files changed:
src/components/VideoPlayer/VideoPlayer.tsx,src/plugins/Emojis/EmojiPicker.tsx.tsc, eslint, and prettier are clean; existingVideoAttachmenttests pass.π¨ UI Changes
No visual changes. Restores
VideoPlayerandEmojiPickerrendering in environments where they previously crashed (Vite 8 / Rolldown, native Node ESM, strict-interop SSR). No screenshots applicable.