Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Call reconnects after leaving #1618

Open
1 of 3 tasks
VisasIespejas opened this issue Dec 11, 2024 · 2 comments
Open
1 of 3 tasks

Call reconnects after leaving #1618

VisasIespejas opened this issue Dec 11, 2024 · 2 comments
Assignees
Labels
bug Something isn't working

Comments

@VisasIespejas
Copy link

Which package/packages do you use?

  • @stream-io/video-react-sdk
  • @stream-io/video-react-native-sdk
  • @stream-io/video-client

Describe the bug
Call will sometimes reconnect after leaving. For me this happens in React development mode when double render causes useEffect to join and leave a call in quick succession (see snippet below for useEffect logic).

To Reproduce

  1. Use this code snippet in React development mode:
let promises = Promise.resolve();
function serially(promise) {
  promises = promises.finally(() => promise());
}

export default function App() {
  const [state, setState] = useState<any>(null);
  useEffect(() => {
    const callCounter = ++counter;
    const client = StreamVideoClient.getOrCreateInstance({
      apiKey,
      user,
      token,
    });
    const call = client.call("default", callId);
    call.state.callingState$.subscribe((state) =>
      console.log(`[${callCounter}] call state ${state}`),
    );
    let isActive = true;
    serially(() =>
      call.join().then(() => isActive && setState({ client, call })),
    );
    return () => {
      isActive = false;
      setState(null);
      serially(() => call.leave());
    };
  }, []);
  return (
    state && (
      <StreamVideo client={state.client}>
        <StreamTheme>
          <StreamCall call={state.call}>
            <SpeakerLayout />
            <CallControls />
          </StreamCall>
        </StreamTheme>
      </StreamVideo>
    )
  );
}
  1. Open the example in browser and allow permissions (you may need to reload multiple times for this to happen)
  2. You may see that the user has joined the call twice. The console logs will show something like this:
    image
    Here you can see that call [1] has reconnected after leaving.

Expected behavior
Leaving the call happens cleanly and it does not reconnect.

Screenshots
Here you can see that the user has connected twice, because call reconnected after leaving:
image

Version

  • SDK version 1.8.1

React / JS client

  • Browser: Edge 131.0.2903.86
    (I experienced the issue in all browsers, but seems to happen more consistently in edge for me)

Node JS client

  • Node version: v20.16.0

Additional context
Add any other context about the problem here.

@VisasIespejas VisasIespejas added the bug Something isn't working label Dec 11, 2024
@oliverlaz
Copy link
Member

oliverlaz commented Dec 13, 2024

hi @VisasIespejas, there seems to be a race condition in creating/disposing calls.

Can you please check if the following snippet helps?

const [client, setClient] = useState<StreamVideoClient>();
const [call, setCall] = useState<Call>();

useEffect(() => {
  const myClient = new StreamVideoClient({ apiKey, user, tokenProvider });
  setClient(myClient);
  return () => {
    myClient.disconnectUser();
    setClient(undefined);
  };
}, []);

useEffect(() => {
  if (!client) return;
  const myCall = client.call("default", callId);
  myCall.join({ create: true }).catch((err) => {
    console.error(`Failed to join the call`, err);
  });

  setCall(myCall);

  return () => {
    setCall(undefined);
    myCall.leave().catch((err) => {
      console.error(`Failed to leave the call`, err);
    });
  };
}, [client]);

if (!client || !call) return null;

  
// the rest of your code

@oliverlaz oliverlaz self-assigned this Dec 13, 2024
@VisasIespejas
Copy link
Author

Hi!

The snippet actually does help because the second hook gets called only once, thanks! 😄

I do still think that this is an issue when the hook that joins the call is activated on mount (and subject to double render), like in this third example:

export function VariantThree({ tokens }) {
  const { apiKey, userId, token, callId } = tokens;

  const [client, setClient] = useState<StreamVideoClient>();

  useEffect(() => {
    const myClient = new StreamVideoClient({
      apiKey,
      user: { id: userId },
      token,
    });
    setClient(myClient);
    return () => {
      myClient.disconnectUser();
      setClient(undefined);
    };
  }, []);

  if (!client) return null;

  return (
    <StreamVideo client={client}>
      <StreamTheme>
        <MyCall callId={callId} />
      </StreamTheme>
    </StreamVideo>
  );
}

function MyCall({ callId }) {
  const client = useStreamVideoClient();
  const [call, setCall] = useState<Call>();

  useEffect(() => {
    if (!client) return;
    const callCounter = ++counter;
    const myCall = client.call("default", callId);
    myCall.state.callingState$.subscribe((state) =>
      console.log(`[${callCounter}] call state ${state}`)
    );
    myCall.join({ create: true }).catch((err) => {
      console.error(`Failed to join the call`, err);
    });

    setCall(myCall);

    return () => {
      setCall(undefined);
      myCall.leave().catch((err) => {
        console.error(`Failed to leave the call`, err);
      });
    };
  }, [client]);

  if (!call) return null;

  return (
    <StreamCall call={call}>
      <SpeakerLayout />
      <CallControls />
    </StreamCall>
  );
}

And here is a sandbox with all three snippets: 😄
https://codesandbox.io/p/sandbox/xtzc4r

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants