zoom-clone
zoom-clone copied to clipboard
unable to get call details when starting a new Meeting.
Hi,
I have started working on this project 2 weeks ago by watching youtube tutorial: Youtube tutorial link and currently have completed till Meeting Setup part of the video (timeStamp: 2:37:07). At this point I should be able to start the VideoPreview component, but am unable to start the call. For debugging I added a early return and found out that below are getting undefined.
const call = useCall(); from MeetingSetup.tsx is undefined.
const { calls } = await client.queryCalls({ filter_conditions: { id } }); from useGetCallById.ts is empty array.
const { call, isCallLoading } = useGetCallById(id); from Meeting component (route: http://localhost:3000/meeting/someID) is undefined.
Early return code:
if (!call)
return (
<p className="text-center text-3xl font-bold text-white">
Call Not Found
</p>
);
If i dont add it, I get the error as below:
if (!call)
throw new Error("useCall must be used within StreamCall component");
I rewatched the video for any errors or if I missed something, everything is same as was told in the video but still unable to start the video.
Below is the code that I am using right now:
Meeting component:
"use client";
import { useState } from "react";
import { useUser } from "@clerk/nextjs";
import { StreamCall, StreamTheme } from "@stream-io/video-react-sdk";
import { useGetCallById } from "@/hooks/useGetCallById";
import MeetingRoom from "@/components/MeetingRoom";
import MeetingSetup from "@/components/MeetingSetup";
import Loader from "@/components/Loader";
const Meeting = ({ params: { id } }: { params: { id: string } }) => {
const { user, isLoaded } = useUser();
const { call, isCallLoading } = useGetCallById(id);
console.log("call", call);
const [isSetupComplete, setIsSetupComplete] = useState(false);
if (!isLoaded || !isCallLoading) return <Loader />;
return (
<main className="h-screen w-full">
<StreamCall call={call}>
<StreamTheme>
{!isSetupComplete ? (
<MeetingSetup setIsSetupComplete={setIsSetupComplete} />
) : (
<MeetingRoom />
)}
</StreamTheme>
</StreamCall>
</main>
);
};
export default Meeting;
MeetingTypeList.tsx:
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { useUser } from "@clerk/nextjs";
import { Call, useStreamVideoClient } from "@stream-io/video-react-sdk";
import { useToast } from "@/components/ui/use-toast";
import HomeCard from "./HomeCard";
import MeetingModal from "./MeetingModal";
const MeetingTypeList = () => {
const { toast } = useToast();
const router = useRouter();
const [meetingState, setMeetingState] = useState<
"isScheduleMeeting" | "isJoiningMeeting" | "isInstantMeeting" | undefined
>();
const { user } = useUser();
const client = useStreamVideoClient();
const [values, setValues] = useState({
dateTime: new Date(),
description: "",
link: "",
});
const [callDetails, setCallDetails] = useState<Call>();
const createMeeting = async () => {
if (!client || !user) return;
try {
if (!values.dateTime) {
toast({ title: "Please select a date and time" });
return;
}
const id = crypto.randomUUID();
const call = client.call("default", id);
if (!call) throw new Error("Failed to create call");
const startsAt =
values.dateTime.toISOString() || new Date(Date.now()).toISOString();
const description = values.description || "Instant Meeting";
await call.getOrCreate({
data: {
starts_at: startsAt,
custom: {
description,
},
},
});
setCallDetails(call);
if (!values.description) {
router.push(`/meeting/:${call.id}`);
}
toast({
title: "Meeting created",
});
} catch (error) {
console.log(error);
toast({
title: "Failed to create meeting",
});
}
};
return (
<section className="grid grid-cols-1 gap-5 md:grid-cols-2 lg:grid-cols-4">
<HomeCard
img="/icons/add-meeting.svg"
title="New Meeting"
description="Start an instant meeting"
handleClick={() => setMeetingState("isInstantMeeting")}
className="bg-orange-1"
/>
<HomeCard
img="/icons/schedule.svg"
title="Schedule Meeting"
description="Plan your meeting"
handleClick={() => setMeetingState("isScheduleMeeting")}
className="bg-blue-1"
/>
<HomeCard
img="/icons/recordings.svg"
title="View Recordings"
description="Check out your recordings"
handleClick={() => setMeetingState("isJoiningMeeting")}
className="bg-purple-1"
/>
<HomeCard
img="/icons/join-meeting.svg"
title="Join Meeting"
description="Via inviation link"
handleClick={() => router.push("/recordings")}
className="bg-yellow-1"
/>
<MeetingModal
isOpen={meetingState === "isInstantMeeting"}
title="Start an Instant Meeting"
className="text-center"
buttonText="Start Meeting"
onClose={() => setMeetingState(undefined)}
handleClick={createMeeting}
/>
</section>
);
};
export default MeetingTypeList;
MeetingSetup.tsx
"use client";
import { useState, useEffect } from "react";
import {
DeviceSettings,
VideoPreview,
useCall,
} from "@stream-io/video-react-sdk";
import { Button } from "./ui/button";
const MeetingSetup = ({
setIsSetupComplete,
}: {
setIsSetupComplete: (value: boolean) => void;
}) => {
const [isMicCamToggledOn, setisMicCamToggledOn] = useState(false);
const call = useCall();
console.log("inside MeetingSetup: call ->", call);
if (!call)
throw new Error("useCall must be used within StreamCall component");
useEffect(() => {
if (isMicCamToggledOn) {
call?.camera.disable();
call?.microphone.disable();
} else {
call?.camera.enable();
call?.microphone.enable();
}
}, [isMicCamToggledOn, call?.camera, call?.microphone]);
return (
<div className="flex flex-col h-screen w-full items-center justify-center gap-3 text-white">
<h1 className="text-2xl font-bold">Setup</h1>
<VideoPreview />
<div className="flex h-16 items-center justify-center gap-3">
<label className="flex items-center justify-center gap-2 font-medium">
<input
type="checkbox"
checked={isMicCamToggledOn}
onChange={(e) => setisMicCamToggledOn(e.target.checked)}
/>
Join with Mic and Camera off
</label>
<DeviceSettings />
</div>
<Button
className="rounded-md bg-green-500 px-4 py-2.5"
onClick={() => {
call.join();
setIsSetupComplete(true);
}}
>
Join Meeting
</Button>
</div>
);
};
export default MeetingSetup;
useGetCallById.ts
import { useEffect, useState } from "react";
import { Call, useStreamVideoClient } from "@stream-io/video-react-sdk";
export const useGetCallById = (id: string | string[]) => {
const [call, setCall] = useState<Call>();
const [isCallLoading, setIsCallLoading] = useState(true);
const client = useStreamVideoClient();
useEffect(() => {
if (!client) return;
const loadCall = async () => {
const { calls } = await client.queryCalls({ filter_conditions: { id } });
console.log("calls", calls);
if (calls.length > 0) setCall(calls[0]);
setIsCallLoading(false);
};
loadCall();
}, [client, id]);
return { call, isCallLoading };
};
My package.json:
{
"name": "yoom",
"description": "Yoom: A video conferencing app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@clerk/nextjs": "^4.29.12",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-toast": "^1.1.5",
"@stream-io/node-sdk": "^0.1.13",
"@stream-io/video-react-sdk": "^0.6.3",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"lucide-react": "^0.365.0",
"next": "14.1.4",
"react": "^18",
"react-dom": "^18",
"tailwind-merge": "^2.2.2",
"tailwindcss-animate": "^1.0.7"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"autoprefixer": "^10.0.1",
"eslint": "^8",
"eslint-config-next": "14.1.4",
"postcss": "^8",
"tailwindcss": "^3.3.0",
"typescript": "^5"
}
}
Please help me, I am stuck for a week in this issue. To check if my environment variables is correct, I cloned this repo and copied the same .env.local and ran the project. It actually ran, so my enviroment variables are correct. I am unable to figure out where am I going wrong. I have pushed the my code to my repo: yoom.
Please guide me. Thanks in advance.
@adrianhajdin any help on this?
I am having this same issue,
I'm getting this error
call on my end is undefined also
I should have cleared my browswer cookies and cache
It is working now
Hi,
I have started working on this project 2 weeks ago by watching youtube tutorial: Youtube tutorial link and currently have completed till Meeting Setup part of the video (
timeStamp: 2:37:07). At this point I should be able to start the VideoPreview component, but am unable to start the call. For debugging I added a early return and found out that below are getting undefined.
const call = useCall();fromMeetingSetup.tsxis undefined.const { calls } = await client.queryCalls({ filter_conditions: { id } });fromuseGetCallById.tsis empty array.const { call, isCallLoading } = useGetCallById(id);fromMeeting component(route: http://localhost:3000/meeting/someID) is undefined.Early return code:
if (!call) return ( <p className="text-center text-3xl font-bold text-white"> Call Not Found </p> );If i dont add it, I get the error as below:
if (!call) throw new Error("useCall must be used within StreamCall component");I rewatched the video for any errors or if I missed something, everything is same as was told in the video but still unable to start the video.
Below is the code that I am using right now:
Meeting component:
"use client"; import { useState } from "react"; import { useUser } from "@clerk/nextjs"; import { StreamCall, StreamTheme } from "@stream-io/video-react-sdk"; import { useGetCallById } from "@/hooks/useGetCallById"; import MeetingRoom from "@/components/MeetingRoom"; import MeetingSetup from "@/components/MeetingSetup"; import Loader from "@/components/Loader"; const Meeting = ({ params: { id } }: { params: { id: string } }) => { const { user, isLoaded } = useUser(); const { call, isCallLoading } = useGetCallById(id); console.log("call", call); const [isSetupComplete, setIsSetupComplete] = useState(false); if (!isLoaded || !isCallLoading) return <Loader />; return ( <main className="h-screen w-full"> <StreamCall call={call}> <StreamTheme> {!isSetupComplete ? ( <MeetingSetup setIsSetupComplete={setIsSetupComplete} /> ) : ( <MeetingRoom /> )} </StreamTheme> </StreamCall> </main> ); }; export default Meeting;MeetingTypeList.tsx:
"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { useUser } from "@clerk/nextjs"; import { Call, useStreamVideoClient } from "@stream-io/video-react-sdk"; import { useToast } from "@/components/ui/use-toast"; import HomeCard from "./HomeCard"; import MeetingModal from "./MeetingModal"; const MeetingTypeList = () => { const { toast } = useToast(); const router = useRouter(); const [meetingState, setMeetingState] = useState< "isScheduleMeeting" | "isJoiningMeeting" | "isInstantMeeting" | undefined >(); const { user } = useUser(); const client = useStreamVideoClient(); const [values, setValues] = useState({ dateTime: new Date(), description: "", link: "", }); const [callDetails, setCallDetails] = useState<Call>(); const createMeeting = async () => { if (!client || !user) return; try { if (!values.dateTime) { toast({ title: "Please select a date and time" }); return; } const id = crypto.randomUUID(); const call = client.call("default", id); if (!call) throw new Error("Failed to create call"); const startsAt = values.dateTime.toISOString() || new Date(Date.now()).toISOString(); const description = values.description || "Instant Meeting"; await call.getOrCreate({ data: { starts_at: startsAt, custom: { description, }, }, }); setCallDetails(call); if (!values.description) { router.push(`/meeting/:${call.id}`); } toast({ title: "Meeting created", }); } catch (error) { console.log(error); toast({ title: "Failed to create meeting", }); } }; return ( <section className="grid grid-cols-1 gap-5 md:grid-cols-2 lg:grid-cols-4"> <HomeCard img="/icons/add-meeting.svg" title="New Meeting" description="Start an instant meeting" handleClick={() => setMeetingState("isInstantMeeting")} className="bg-orange-1" /> <HomeCard img="/icons/schedule.svg" title="Schedule Meeting" description="Plan your meeting" handleClick={() => setMeetingState("isScheduleMeeting")} className="bg-blue-1" /> <HomeCard img="/icons/recordings.svg" title="View Recordings" description="Check out your recordings" handleClick={() => setMeetingState("isJoiningMeeting")} className="bg-purple-1" /> <HomeCard img="/icons/join-meeting.svg" title="Join Meeting" description="Via inviation link" handleClick={() => router.push("/recordings")} className="bg-yellow-1" /> <MeetingModal isOpen={meetingState === "isInstantMeeting"} title="Start an Instant Meeting" className="text-center" buttonText="Start Meeting" onClose={() => setMeetingState(undefined)} handleClick={createMeeting} /> </section> ); }; export default MeetingTypeList;MeetingSetup.tsx
"use client"; import { useState, useEffect } from "react"; import { DeviceSettings, VideoPreview, useCall, } from "@stream-io/video-react-sdk"; import { Button } from "./ui/button"; const MeetingSetup = ({ setIsSetupComplete, }: { setIsSetupComplete: (value: boolean) => void; }) => { const [isMicCamToggledOn, setisMicCamToggledOn] = useState(false); const call = useCall(); console.log("inside MeetingSetup: call ->", call); if (!call) throw new Error("useCall must be used within StreamCall component"); useEffect(() => { if (isMicCamToggledOn) { call?.camera.disable(); call?.microphone.disable(); } else { call?.camera.enable(); call?.microphone.enable(); } }, [isMicCamToggledOn, call?.camera, call?.microphone]); return ( <div className="flex flex-col h-screen w-full items-center justify-center gap-3 text-white"> <h1 className="text-2xl font-bold">Setup</h1> <VideoPreview /> <div className="flex h-16 items-center justify-center gap-3"> <label className="flex items-center justify-center gap-2 font-medium"> <input type="checkbox" checked={isMicCamToggledOn} onChange={(e) => setisMicCamToggledOn(e.target.checked)} /> Join with Mic and Camera off </label> <DeviceSettings /> </div> <Button className="rounded-md bg-green-500 px-4 py-2.5" onClick={() => { call.join(); setIsSetupComplete(true); }} > Join Meeting </Button> </div> ); }; export default MeetingSetup;useGetCallById.ts
import { useEffect, useState } from "react"; import { Call, useStreamVideoClient } from "@stream-io/video-react-sdk"; export const useGetCallById = (id: string | string[]) => { const [call, setCall] = useState<Call>(); const [isCallLoading, setIsCallLoading] = useState(true); const client = useStreamVideoClient(); useEffect(() => { if (!client) return; const loadCall = async () => { const { calls } = await client.queryCalls({ filter_conditions: { id } }); console.log("calls", calls); if (calls.length > 0) setCall(calls[0]); setIsCallLoading(false); }; loadCall(); }, [client, id]); return { call, isCallLoading }; };My
package.json:{ "name": "yoom", "description": "Yoom: A video conferencing app", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "@clerk/nextjs": "^4.29.12", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-toast": "^1.1.5", "@stream-io/node-sdk": "^0.1.13", "@stream-io/video-react-sdk": "^0.6.3", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "lucide-react": "^0.365.0", "next": "14.1.4", "react": "^18", "react-dom": "^18", "tailwind-merge": "^2.2.2", "tailwindcss-animate": "^1.0.7" }, "devDependencies": { "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", "autoprefixer": "^10.0.1", "eslint": "^8", "eslint-config-next": "14.1.4", "postcss": "^8", "tailwindcss": "^3.3.0", "typescript": "^5" } }Please help me, I am stuck for a week in this issue. To check if my environment variables is correct, I cloned this repo and copied the same
.env.localand ran the project. It actually ran, so my enviroment variables are correct. I am unable to figure out where am I going wrong. I have pushed the my code to my repo: yoom.Please guide me. Thanks in advance.
Hey Could you find any solution for this ?
Hi, I have started working on this project 2 weeks ago by watching youtube tutorial: Youtube tutorial link and currently have completed till Meeting Setup part of the video (
timeStamp: 2:37:07). At this point I should be able to start the VideoPreview component, but am unable to start the call. For debugging I added a early return and found out that below are getting undefined.const call = useCall();fromMeetingSetup.tsxis undefined.const { calls } = await client.queryCalls({ filter_conditions: { id } });fromuseGetCallById.tsis empty array.const { call, isCallLoading } = useGetCallById(id);fromMeeting component(route: http://localhost:3000/meeting/someID) is undefined. Early return code:if (!call) return ( <p className="text-center text-3xl font-bold text-white"> Call Not Found </p> );If i dont add it, I get the error as below:
if (!call) throw new Error("useCall must be used within StreamCall component");I rewatched the video for any errors or if I missed something, everything is same as was told in the video but still unable to start the video. Below is the code that I am using right now: Meeting component:
"use client"; import { useState } from "react"; import { useUser } from "@clerk/nextjs"; import { StreamCall, StreamTheme } from "@stream-io/video-react-sdk"; import { useGetCallById } from "@/hooks/useGetCallById"; import MeetingRoom from "@/components/MeetingRoom"; import MeetingSetup from "@/components/MeetingSetup"; import Loader from "@/components/Loader"; const Meeting = ({ params: { id } }: { params: { id: string } }) => { const { user, isLoaded } = useUser(); const { call, isCallLoading } = useGetCallById(id); console.log("call", call); const [isSetupComplete, setIsSetupComplete] = useState(false); if (!isLoaded || !isCallLoading) return <Loader />; return ( <main className="h-screen w-full"> <StreamCall call={call}> <StreamTheme> {!isSetupComplete ? ( <MeetingSetup setIsSetupComplete={setIsSetupComplete} /> ) : ( <MeetingRoom /> )} </StreamTheme> </StreamCall> </main> ); }; export default Meeting;MeetingTypeList.tsx:
"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { useUser } from "@clerk/nextjs"; import { Call, useStreamVideoClient } from "@stream-io/video-react-sdk"; import { useToast } from "@/components/ui/use-toast"; import HomeCard from "./HomeCard"; import MeetingModal from "./MeetingModal"; const MeetingTypeList = () => { const { toast } = useToast(); const router = useRouter(); const [meetingState, setMeetingState] = useState< "isScheduleMeeting" | "isJoiningMeeting" | "isInstantMeeting" | undefined >(); const { user } = useUser(); const client = useStreamVideoClient(); const [values, setValues] = useState({ dateTime: new Date(), description: "", link: "", }); const [callDetails, setCallDetails] = useState<Call>(); const createMeeting = async () => { if (!client || !user) return; try { if (!values.dateTime) { toast({ title: "Please select a date and time" }); return; } const id = crypto.randomUUID(); const call = client.call("default", id); if (!call) throw new Error("Failed to create call"); const startsAt = values.dateTime.toISOString() || new Date(Date.now()).toISOString(); const description = values.description || "Instant Meeting"; await call.getOrCreate({ data: { starts_at: startsAt, custom: { description, }, }, }); setCallDetails(call); if (!values.description) { router.push(`/meeting/:${call.id}`); } toast({ title: "Meeting created", }); } catch (error) { console.log(error); toast({ title: "Failed to create meeting", }); } }; return ( <section className="grid grid-cols-1 gap-5 md:grid-cols-2 lg:grid-cols-4"> <HomeCard img="/icons/add-meeting.svg" title="New Meeting" description="Start an instant meeting" handleClick={() => setMeetingState("isInstantMeeting")} className="bg-orange-1" /> <HomeCard img="/icons/schedule.svg" title="Schedule Meeting" description="Plan your meeting" handleClick={() => setMeetingState("isScheduleMeeting")} className="bg-blue-1" /> <HomeCard img="/icons/recordings.svg" title="View Recordings" description="Check out your recordings" handleClick={() => setMeetingState("isJoiningMeeting")} className="bg-purple-1" /> <HomeCard img="/icons/join-meeting.svg" title="Join Meeting" description="Via inviation link" handleClick={() => router.push("/recordings")} className="bg-yellow-1" /> <MeetingModal isOpen={meetingState === "isInstantMeeting"} title="Start an Instant Meeting" className="text-center" buttonText="Start Meeting" onClose={() => setMeetingState(undefined)} handleClick={createMeeting} /> </section> ); }; export default MeetingTypeList;MeetingSetup.tsx
"use client"; import { useState, useEffect } from "react"; import { DeviceSettings, VideoPreview, useCall, } from "@stream-io/video-react-sdk"; import { Button } from "./ui/button"; const MeetingSetup = ({ setIsSetupComplete, }: { setIsSetupComplete: (value: boolean) => void; }) => { const [isMicCamToggledOn, setisMicCamToggledOn] = useState(false); const call = useCall(); console.log("inside MeetingSetup: call ->", call); if (!call) throw new Error("useCall must be used within StreamCall component"); useEffect(() => { if (isMicCamToggledOn) { call?.camera.disable(); call?.microphone.disable(); } else { call?.camera.enable(); call?.microphone.enable(); } }, [isMicCamToggledOn, call?.camera, call?.microphone]); return ( <div className="flex flex-col h-screen w-full items-center justify-center gap-3 text-white"> <h1 className="text-2xl font-bold">Setup</h1> <VideoPreview /> <div className="flex h-16 items-center justify-center gap-3"> <label className="flex items-center justify-center gap-2 font-medium"> <input type="checkbox" checked={isMicCamToggledOn} onChange={(e) => setisMicCamToggledOn(e.target.checked)} /> Join with Mic and Camera off </label> <DeviceSettings /> </div> <Button className="rounded-md bg-green-500 px-4 py-2.5" onClick={() => { call.join(); setIsSetupComplete(true); }} > Join Meeting </Button> </div> ); }; export default MeetingSetup;useGetCallById.ts
import { useEffect, useState } from "react"; import { Call, useStreamVideoClient } from "@stream-io/video-react-sdk"; export const useGetCallById = (id: string | string[]) => { const [call, setCall] = useState<Call>(); const [isCallLoading, setIsCallLoading] = useState(true); const client = useStreamVideoClient(); useEffect(() => { if (!client) return; const loadCall = async () => { const { calls } = await client.queryCalls({ filter_conditions: { id } }); console.log("calls", calls); if (calls.length > 0) setCall(calls[0]); setIsCallLoading(false); }; loadCall(); }, [client, id]); return { call, isCallLoading }; };My
package.json:{ "name": "yoom", "description": "Yoom: A video conferencing app", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "@clerk/nextjs": "^4.29.12", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-toast": "^1.1.5", "@stream-io/node-sdk": "^0.1.13", "@stream-io/video-react-sdk": "^0.6.3", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "lucide-react": "^0.365.0", "next": "14.1.4", "react": "^18", "react-dom": "^18", "tailwind-merge": "^2.2.2", "tailwindcss-animate": "^1.0.7" }, "devDependencies": { "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", "autoprefixer": "^10.0.1", "eslint": "^8", "eslint-config-next": "14.1.4", "postcss": "^8", "tailwindcss": "^3.3.0", "typescript": "^5" } }Please help me, I am stuck for a week in this issue. To check if my environment variables is correct, I cloned this repo and copied the same
.env.localand ran the project. It actually ran, so my enviroment variables are correct. I am unable to figure out where am I going wrong. I have pushed the my code to my repo: yoom. Please guide me. Thanks in advance.Hey Could you find any solution for this ?
I tried creating another workspace and starting from scratch. still the same issue. So after completing tutorial I cloned this repo and it worked. TBH, couldn't find a solution for this.