-
Notifications
You must be signed in to change notification settings - Fork 135
Fix useSession return value stability
#1230
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
Changes from 5 commits
9d8b718
0293371
6a1fc06
cafdf8e
a6f22da
9be2530
f48ffa5
424bc0b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| '@livekit/components-react': patch | ||
| --- | ||
|
|
||
| Fix useSession return value stability |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -154,6 +154,88 @@ type UseSessionCommonOptions = { | |
| type UseSessionConfigurableOptions = UseSessionCommonOptions & TokenSourceFetchOptions; | ||
| type UseSessionFixedOptions = UseSessionCommonOptions; | ||
|
|
||
| /** | ||
| * Given two TokenSourceFetchOptions values, check to see if they are deep equal. | ||
| * | ||
| * FIXME: swap this for an import from livekit-client once | ||
| * https://github.com/livekit/client-sdk-js/pull/1733 is merged and published! | ||
| * */ | ||
| function areTokenSourceFetchOptionsEqual(a: TokenSourceFetchOptions, b: TokenSourceFetchOptions) { | ||
| const allKeysSet = new Set([...Object.keys(a), ...Object.keys(b)]) as Set< | ||
| keyof TokenSourceFetchOptions | ||
| >; | ||
|
|
||
| for (const key of allKeysSet) { | ||
| switch (key) { | ||
| case 'roomName': | ||
| case 'participantName': | ||
| case 'participantIdentity': | ||
| case 'participantMetadata': | ||
| case 'participantAttributes': | ||
| case 'agentName': | ||
| case 'agentMetadata': | ||
| if (a[key] !== b[key]) { | ||
| return false; | ||
| } | ||
| break; | ||
| default: | ||
| // ref: https://stackoverflow.com/a/58009992 | ||
| const exhaustiveCheckedKey: never = key; | ||
| throw new Error(`Options key ${exhaustiveCheckedKey} not being checked for equality!`); | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| /** Internal hook used by useSession to manage creating a function that properly invokes | ||
| * tokenSource.fetch(...) with any fetch options */ | ||
| function useSessionTokenSourceFetch( | ||
| tokenSource: TokenSourceConfigurable | TokenSourceFixed, | ||
| unstableRestOptions: Exclude<UseSessionConfigurableOptions, keyof UseSessionCommonOptions>, | ||
| ) { | ||
| const isConfigurable = tokenSource instanceof TokenSourceConfigurable; | ||
|
|
||
| const [memoizedTokenFetchOptions, setMemoizedTokenFetchOptions] = | ||
|
||
| React.useState<TokenSourceFetchOptions | null>(() => { | ||
| if (isConfigurable) { | ||
| return unstableRestOptions; | ||
| } else { | ||
| return null; | ||
| } | ||
| }); | ||
| React.useEffect(() => { | ||
| if (!isConfigurable) { | ||
| setMemoizedTokenFetchOptions(null); | ||
| return; | ||
| } | ||
|
|
||
| if ( | ||
| memoizedTokenFetchOptions !== null && | ||
| areTokenSourceFetchOptionsEqual(memoizedTokenFetchOptions, unstableRestOptions) | ||
| ) { | ||
| return; | ||
| } | ||
|
|
||
| setMemoizedTokenFetchOptions(unstableRestOptions); | ||
| }, [isConfigurable, unstableRestOptions]); | ||
|
|
||
| const tokenSourceFetch = React.useCallback(async () => { | ||
| if (isConfigurable) { | ||
| if (!memoizedTokenFetchOptions) { | ||
| throw new Error( | ||
| `AgentSession - memoized token fetch options are not set, but the passed tokenSource was an instance of TokenSourceConfigurable. If you are seeing this please make a new GitHub issue!`, | ||
| ); | ||
| } | ||
|
||
| return tokenSource.fetch(memoizedTokenFetchOptions); | ||
| } else { | ||
| return tokenSource.fetch(); | ||
| } | ||
| }, [isConfigurable, tokenSource, memoizedTokenFetchOptions]); | ||
|
|
||
| return tokenSourceFetch; | ||
| } | ||
|
|
||
| /** | ||
| * A Session represents a manages connection to a Room which can contain Agents. | ||
| * @public | ||
|
|
@@ -427,15 +509,7 @@ export function useSession( | |
| ), | ||
| ); | ||
|
|
||
| const tokenSourceFetch = React.useCallback(async () => { | ||
| const isConfigurable = tokenSource instanceof TokenSourceConfigurable; | ||
| if (isConfigurable) { | ||
| const tokenFetchOptions = restOptions as UseSessionConfigurableOptions; | ||
| return tokenSource.fetch(tokenFetchOptions); | ||
| } else { | ||
| return tokenSource.fetch(); | ||
| } | ||
| }, [tokenSource, restOptions]); | ||
| const tokenSourceFetch = useSessionTokenSourceFetch(tokenSource, restOptions); | ||
|
|
||
| const start = React.useCallback( | ||
| async (connectOptions: SessionConnectOptions = {}) => { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chore: This has been copied from here: livekit/client-sdk-js#1733. I did this so I could test the change but IMO this copied code shouldn't be merged.
So, before this should be merged, get the above linked pull request deployed into a new version on npm, then delete this code and update it to be an import.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, I forgot to do this before merging 🤦 . I will do this as part of the follow up change.