twilio-video.js
twilio-video.js copied to clipboard
Uncaught TypeError: Class extends value [object Object] is not a constructor or null in React Remix
Hi, I am getting the below error when I try to use twilio-video in my React Remix app, as far as I know the error shows when it is running imports, how can I fix this?
Uncaught TypeError: Class extends value [object Object] is not a constructor or null at mediasignaling.js:1:1 at mediasignaling.js:7:30 at node_modules/twilio-video/es5/signaling/v2/mediasignaling.js (mediasignaling.js:76:1) at __require2 (chunk-WX2OHN6X.js:18:50) at node_modules/twilio-video/es5/signaling/v2/dominantspeakersignaling.js (dominantspeakersignaling.js:3:24) at __require2 (chunk-WX2OHN6X.js:18:50) at node_modules/twilio-video/es5/signaling/v2/room.js (room.js:4:34) at __require2 (chunk-WX2OHN6X.js:18:50) at node_modules/twilio-video/es5/signaling/v2/cancelableroomsignalingpromise.js (cancelableroomsignalingpromise.js:5:23) at __require2 (chunk-WX2OHN6X.js:18:50)
I used
const Video = require('twilio-video')
and
import * as Video from 'twilio-video'
both are not working
Here is my tsconfig.json
"compilerOptions": { "lib": [ "DOM", "DOM.Iterable", "ES2019" ], "isolatedModules": true, "esModuleInterop": true, "jsx": "react-jsx", "moduleResolution": "node", "resolveJsonModule": true, "target": "ES2019", "strict": true, "allowJs": true, "forceConsistentCasingInFileNames": true, "baseUrl": ".",
I ran into the same issue, but was unable to fix it via imports or config. I ended up instead importing the CDN version during page load and ensuring it only ran in client side.
So, on the routes I want to use Twilio, I added:
export const handle = {
scripts: () => [
{
src: "//sdk.twilio.com/js/video/releases/2.27.0/twilio-video.min.js",
},
],
};
Then, in my root.tsx
file, I use the <ExternalScripts />
component from remix-utils
which looks into the handle
for each route.
In the components themselves, I ended up wrapping any video components in the <ClientOnly>
component from the same remix-utils
package to ensure it's browser side only. Like this:
<ClientOnly fallback={<Text>Please wait....</Text>}>
{() => (
<MyVideoComponent />
)}
</ClientOnly>
Lastly - to get type defs, I wrote a super hacky, function like this:
/* eslint-disable @typescript-eslint/consistent-type-imports */
export function getBrowserTwilio() {
if (typeof document === "undefined") {
// Server should just not do anything. Wrapping all the stuff in <ClientOnly> should ensure that
return {} as typeof import("twilio-video");
}
return (window as any).Twilio.Video as typeof import("twilio-video");
}
When I call getBrowserTwilio
- I get an object which returns the Twilio.Video
object on the window
. It works, but certainly not ideal. If we end up continuing with Twilio, we'll likely dig deeper and hopefully find a cleaner option.
@mason-t3h ,
Thanks for writing in. Can I have access to your repository so that I can try a few things on my local dev machine?
Also having this issue, running @remix-run/dev 1.19.1