Skip to content

Commit 9b7296a

Browse files
authored
Fix toggle hydration error (#1069)
1 parent d00db1e commit 9b7296a

File tree

3 files changed

+23
-26
lines changed

3 files changed

+23
-26
lines changed

.changeset/chatty-cups-turn.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@livekit/components-react": patch
3+
---
4+
5+
Fix toggle hydration error

packages/react/src/components/controls/TrackToggle.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,16 @@ export const TrackToggle: <T extends ToggleSource>(
3939
T extends ToggleSource,
4040
>({ showIcon, ...props }: TrackToggleProps<T>, ref: React.ForwardedRef<HTMLButtonElement>) {
4141
const { buttonProps, enabled } = useTrackToggle(props);
42+
const [isClient, setIsClient] = React.useState(false);
43+
React.useEffect(() => {
44+
setIsClient(true);
45+
}, []);
4246
return (
43-
<button ref={ref} {...buttonProps}>
44-
{(showIcon ?? true) && getSourceIcon(props.source, enabled)}
45-
{props.children}
46-
</button>
47+
isClient && (
48+
<button ref={ref} {...buttonProps}>
49+
{(showIcon ?? true) && getSourceIcon(props.source, enabled)}
50+
{props.children}
51+
</button>
52+
)
4753
);
4854
});

packages/react/src/prefabs/PreJoin.tsx

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import { log } from '@livekit/components-core';
2222
import { ParticipantPlaceholder } from '../assets/images';
2323
import { useMediaDevices, usePersistentUserChoices } from '../hooks';
2424
import { useWarnAboutMissingStyles } from '../hooks/useWarnAboutMissingStyles';
25-
import { defaultUserChoices } from '@livekit/components-core';
2625
import { roomOptionsStringifyReplacer } from '../utils';
2726

2827
/**
@@ -231,17 +230,6 @@ export function PreJoin({
231230
videoProcessor,
232231
...htmlProps
233232
}: PreJoinProps) {
234-
const [userChoices, setUserChoices] = React.useState(defaultUserChoices);
235-
236-
// TODO: Remove and pipe `defaults` object directly into `usePersistentUserChoices` once we fully switch from type `LocalUserChoices` to `UserChoices`.
237-
const partialDefaults: Partial<LocalUserChoices> = {
238-
...(defaults.audioDeviceId !== undefined && { audioDeviceId: defaults.audioDeviceId }),
239-
...(defaults.videoDeviceId !== undefined && { videoDeviceId: defaults.videoDeviceId }),
240-
...(defaults.audioEnabled !== undefined && { audioEnabled: defaults.audioEnabled }),
241-
...(defaults.videoEnabled !== undefined && { videoEnabled: defaults.videoEnabled }),
242-
...(defaults.username !== undefined && { username: defaults.username }),
243-
};
244-
245233
const {
246234
userChoices: initialUserChoices,
247235
saveAudioInputDeviceId,
@@ -250,21 +238,19 @@ export function PreJoin({
250238
saveVideoInputEnabled,
251239
saveUsername,
252240
} = usePersistentUserChoices({
253-
defaults: partialDefaults,
241+
defaults,
254242
preventSave: !persistUserChoices,
255243
preventLoad: !persistUserChoices,
256244
});
257245

246+
const [userChoices, setUserChoices] = React.useState(initialUserChoices);
247+
258248
// Initialize device settings
259-
const [audioEnabled, setAudioEnabled] = React.useState<boolean>(initialUserChoices.audioEnabled);
260-
const [videoEnabled, setVideoEnabled] = React.useState<boolean>(initialUserChoices.videoEnabled);
261-
const [audioDeviceId, setAudioDeviceId] = React.useState<string>(
262-
initialUserChoices.audioDeviceId,
263-
);
264-
const [videoDeviceId, setVideoDeviceId] = React.useState<string>(
265-
initialUserChoices.videoDeviceId,
266-
);
267-
const [username, setUsername] = React.useState(initialUserChoices.username);
249+
const [audioEnabled, setAudioEnabled] = React.useState<boolean>(userChoices.audioEnabled);
250+
const [videoEnabled, setVideoEnabled] = React.useState<boolean>(userChoices.videoEnabled);
251+
const [audioDeviceId, setAudioDeviceId] = React.useState<string>(userChoices.audioDeviceId);
252+
const [videoDeviceId, setVideoDeviceId] = React.useState<string>(userChoices.videoDeviceId);
253+
const [username, setUsername] = React.useState(userChoices.username);
268254

269255
// Save user choices to persistent storage.
270256
React.useEffect(() => {

0 commit comments

Comments
 (0)