Skip to content

Commit b3daaa0

Browse files
committed
fix: make agent.waitUntilAvailable more stable
It had a dependency on `state` so that it could bail if the state was the expected state when being initially called, but this had the side effect of causing it to change reference often. So, cache this in a ref instead.
1 parent 6cc33da commit b3daaa0

File tree

2 files changed

+49
-33
lines changed

2 files changed

+49
-33
lines changed

packages/react/src/hooks/useAgent.ts

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,50 @@ export const useAgentTimeoutIdStore = (): {
241241

242242
type SessionStub = Pick<UseSessionReturn, 'connectionState' | 'room' | 'internal'>;
243243

244+
/** Internal hook used by useAgent which generates a function that when called, will return a
245+
* promise which resolves when agent.isAvailable is enabled. */
246+
function useAgentWaitUntilAvailable(emitter: TypedEventEmitter<AgentCallbacks>, state: AgentState) {
247+
const stateRef = React.useRef(state);
248+
React.useEffect(() => {
249+
stateRef.current = state;
250+
}, [state]);
251+
252+
const waitUntilAvailable = React.useCallback(
253+
async (signal?: AbortSignal) => {
254+
const { isAvailable } = generateDerivedStateValues(stateRef.current);
255+
if (isAvailable) {
256+
return;
257+
}
258+
259+
return new Promise<void>((resolve, reject) => {
260+
const stateChangedHandler = (state: AgentState) => {
261+
const { isAvailable } = generateDerivedStateValues(state);
262+
if (!isAvailable) {
263+
return;
264+
}
265+
cleanup();
266+
resolve();
267+
};
268+
const abortHandler = () => {
269+
cleanup();
270+
reject(new Error('useAgent.waitUntilAvailable - signal aborted'));
271+
};
272+
273+
const cleanup = () => {
274+
emitter.off(AgentEvent.StateChanged, stateChangedHandler);
275+
signal?.removeEventListener('abort', abortHandler);
276+
};
277+
278+
emitter.on(AgentEvent.StateChanged, stateChangedHandler);
279+
signal?.addEventListener('abort', abortHandler);
280+
});
281+
},
282+
[emitter],
283+
);
284+
285+
return waitUntilAvailable;
286+
}
287+
244288
/**
245289
* useAgent encapculates all agent state, normalizing some quirks around how LiveKit Agents work.
246290
* @public
@@ -536,38 +580,7 @@ export function useAgent(session?: SessionStub): UseAgentReturn {
536580
isBufferingSpeech,
537581
]);
538582

539-
const waitUntilAvailable = React.useCallback(
540-
async (signal?: AbortSignal) => {
541-
const { isAvailable } = generateDerivedStateValues(state);
542-
if (isAvailable) {
543-
return;
544-
}
545-
546-
return new Promise<void>((resolve, reject) => {
547-
const stateChangedHandler = (state: AgentState) => {
548-
const { isAvailable } = generateDerivedStateValues(state);
549-
if (!isAvailable) {
550-
return;
551-
}
552-
cleanup();
553-
resolve();
554-
};
555-
const abortHandler = () => {
556-
cleanup();
557-
reject(new Error('useAgent.waitUntilAvailable - signal aborted'));
558-
};
559-
560-
const cleanup = () => {
561-
emitter.off(AgentEvent.StateChanged, stateChangedHandler);
562-
signal?.removeEventListener('abort', abortHandler);
563-
};
564-
565-
emitter.on(AgentEvent.StateChanged, stateChangedHandler);
566-
signal?.addEventListener('abort', abortHandler);
567-
});
568-
},
569-
[state, emitter],
570-
);
583+
const waitUntilAvailable = useAgentWaitUntilAvailable(emitter, state);
571584

572585
const waitUntilCamera = React.useCallback(
573586
(signal?: AbortSignal) => {

packages/react/src/hooks/useSession.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,10 @@ export function useSession(
489489
emitter.emit(SessionEvent.ConnectionStateChanged, conversationState.connectionState);
490490
}, [emitter, conversationState.connectionState]);
491491

492-
const waitUntilConnectionState = useSessionWaitUntilConnectionState(emitter, conversationState.connectionState);
492+
const waitUntilConnectionState = useSessionWaitUntilConnectionState(
493+
emitter,
494+
conversationState.connectionState,
495+
);
493496

494497
const waitUntilConnected = React.useCallback(
495498
async (signal?: AbortSignal) => {

0 commit comments

Comments
 (0)