Skip to content

Commit bbd984f

Browse files
authored
Merge pull request #4811 from daily-co/eng-4075-uselocalparticipant-does-not-resolve
ENG-4075 Fix useLocalParticipant state initialization
2 parents d2d567d + 7497e09 commit bbd984f

File tree

3 files changed

+45
-60
lines changed

3 files changed

+45
-60
lines changed

src/hooks/useLocalParticipant.ts

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { useCallback, useEffect } from 'react';
1+
import { DailyEventObjectParticipant } from '@daily-co/daily-js';
2+
import { useEffect } from 'react';
23
import { atom, useRecoilCallback, useRecoilValue } from 'recoil';
34

45
import { useDaily } from './useDaily';
5-
import { useDailyEvent } from './useDailyEvent';
66
import { useParticipant } from './useParticipant';
77

88
const localIdState = atom<string>({
@@ -19,25 +19,27 @@ export const useLocalParticipant = (): ReturnType<typeof useParticipant> => {
1919

2020
const initState = useRecoilCallback(
2121
({ set }) =>
22-
() => {
23-
const local = daily?.participants()?.local;
24-
if (!local) return;
25-
set(localIdState, local.session_id);
22+
(session_id: string) => {
23+
if (!session_id) return;
24+
set(localIdState, session_id);
2625
},
27-
[daily]
26+
[]
2827
);
2928
useEffect(() => {
30-
if (!daily) return;
31-
initState();
32-
}, [daily, initState]);
33-
34-
useDailyEvent(
35-
'loaded',
36-
useCallback(() => {
37-
// Arbitrary timeout. See https://codepen.io/Regaddi/pen/zYdVBja
38-
setTimeout(initState, 1000);
39-
}, [initState])
40-
);
29+
if (!daily || localId) return;
30+
if (daily.participants()?.local) {
31+
initState(daily.participants().local.session_id);
32+
return;
33+
}
34+
const handleParticipantUpdated = (ev?: DailyEventObjectParticipant) => {
35+
if (!ev?.participant?.local) return;
36+
initState(ev?.participant?.session_id);
37+
};
38+
daily.on('participant-updated', handleParticipantUpdated);
39+
return () => {
40+
daily.off('participant-updated', handleParticipantUpdated);
41+
};
42+
}, [daily, initState, localId]);
4143

4244
return useParticipant(localId);
4345
};
Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
/// <reference types="@types/jest" />
22

3-
import DailyIframe, {
4-
DailyCall,
5-
DailyEvent,
6-
DailyEventObject,
7-
} from '@daily-co/daily-js';
3+
import DailyIframe, { DailyCall } from '@daily-co/daily-js';
84
import { act, renderHook } from '@testing-library/react-hooks';
95
import React from 'react';
106

117
import { DailyProvider } from '../../src/DailyProvider';
128
import { useLocalParticipant } from '../../src/hooks/useLocalParticipant';
9+
import * as useParticipantModule from '../../src/hooks/useParticipant';
1310

1411
const createWrapper =
1512
(callObject: DailyCall = DailyIframe.createCallObject()): React.FC =>
@@ -30,6 +27,7 @@ describe('useLocalParticipant', () => {
3027
const daily = DailyIframe.createCallObject();
3128
(daily.participants as jest.Mock).mockImplementation(() => ({
3229
local: {
30+
local: true,
3331
session_id: 'local',
3432
user_name: '',
3533
},
@@ -39,45 +37,33 @@ describe('useLocalParticipant', () => {
3937
});
4038
await waitFor(() => {
4139
expect(result.current).toEqual({
40+
local: true,
4241
session_id: 'local',
4342
user_name: '',
4443
});
4544
});
4645
});
47-
it('loaded event triggers a 1s timeout to init state', async () => {
48-
jest.useFakeTimers();
49-
const setTimeoutSpy = jest.spyOn(window, 'setTimeout');
46+
it('participant-updated event inits state and calls useParticipant with session_id', async () => {
5047
const daily = DailyIframe.createCallObject();
51-
const { result, waitFor } = renderHook(() => useLocalParticipant(), {
48+
const spy = jest.spyOn(useParticipantModule, 'useParticipant');
49+
const { waitFor } = renderHook(() => useLocalParticipant(), {
5250
wrapper: createWrapper(daily),
5351
});
54-
const event: DailyEvent = 'loaded';
55-
const payload: DailyEventObject = {
56-
action: event,
57-
};
58-
act(() => {
59-
// @ts-ignore
60-
daily.emit(event, payload);
61-
});
62-
await waitFor(() => {
63-
expect(setTimeoutSpy).toBeCalledWith(expect.any(Function), 1000);
64-
expect(result.current).toBeNull();
65-
});
66-
(daily.participants as jest.Mock).mockImplementation(() => ({
67-
local: {
52+
const action = 'participant-updated';
53+
const payload = {
54+
action,
55+
participant: {
56+
local: true,
6857
session_id: 'local',
6958
user_name: '',
7059
},
71-
}));
60+
};
7261
act(() => {
73-
jest.runAllTimers();
62+
// @ts-ignore
63+
daily.emit('participant-updated', payload);
7464
});
7565
await waitFor(() => {
76-
expect(result.current).toEqual({
77-
session_id: 'local',
78-
user_name: '',
79-
});
66+
expect(spy).toHaveBeenCalledWith('local');
8067
});
81-
jest.useRealTimers();
8268
});
8369
});

test/hooks/useRecording.test.tsx

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,20 @@ import DailyIframe, {
1212
import { act, renderHook } from '@testing-library/react-hooks';
1313
import faker from 'faker';
1414
import React from 'react';
15-
import { RecoilRoot } from 'recoil';
1615

1716
import { DailyProvider } from '../../src/DailyProvider';
1817
import { useRecording } from '../../src/hooks/useRecording';
1918

19+
const localId = faker.datatype.uuid();
20+
21+
jest.mock('../../src/hooks/useLocalParticipant', () => ({
22+
useLocalParticipant: () => ({ session_id: localId }),
23+
}));
24+
2025
const createWrapper =
2126
(callObject: DailyCall = DailyIframe.createCallObject()): React.FC =>
2227
({ children }) =>
23-
(
24-
<DailyProvider callObject={callObject}>
25-
<RecoilRoot>{children}</RecoilRoot>
26-
</DailyProvider>
27-
);
28+
<DailyProvider callObject={callObject}>{children}</DailyProvider>;
2829

2930
describe('useRecording', () => {
3031
it('returns default state and functions', async () => {
@@ -185,16 +186,12 @@ describe('useRecording', () => {
185186
});
186187
it('single-participant recording for other participant sets isLocalParticipantRecorded to false', async () => {
187188
const daily = DailyIframe.createCallObject();
188-
const localId = faker.datatype.uuid();
189-
const otherId = faker.datatype.uuid();
189+
const otherId = 'other';
190190
(daily.participants as jest.Mock).mockImplementation(() => ({
191191
local: {
192192
session_id: localId,
193193
},
194194
}));
195-
jest.mock('../../src/hooks/useLocalParticipant', () => ({
196-
useLocalParticipant: () => ({ session_id: localId }),
197-
}));
198195
const { result, waitFor } = renderHook(() => useRecording(), {
199196
wrapper: createWrapper(daily),
200197
});
@@ -207,7 +204,7 @@ describe('useRecording', () => {
207204
},
208205
local: false,
209206
recordingId: faker.datatype.uuid(),
210-
startedBy: faker.datatype.uuid(),
207+
startedBy: localId,
211208
type: 'cloud',
212209
};
213210
act(() => {

0 commit comments

Comments
 (0)