Clarify what useLatest is for

I was touching this file and noticed a chance to clean up this little TODO comment by swapping in our useLatest hook and giving it better documentation.
This commit is contained in:
Robin
2025-02-24 17:45:40 +07:00
parent 832a5aaf57
commit 9b59544db2
2 changed files with 16 additions and 21 deletions

View File

@@ -5,14 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details. Please see LICENSE in the repository root for full details.
*/ */
import { import { type FC, useCallback, useEffect, useMemo, useState } from "react";
type FC,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import { type MatrixClient } from "matrix-js-sdk/src/client"; import { type MatrixClient } from "matrix-js-sdk/src/client";
import { import {
Room, Room,
@@ -40,10 +33,7 @@ import { useProfile } from "../profile/useProfile";
import { findDeviceByName } from "../utils/media"; import { findDeviceByName } from "../utils/media";
import { ActiveCall } from "./InCallView"; import { ActiveCall } from "./InCallView";
import { MUTE_PARTICIPANT_COUNT, type MuteStates } from "./MuteStates"; import { MUTE_PARTICIPANT_COUNT, type MuteStates } from "./MuteStates";
import { import { useMediaDevices } from "../livekit/MediaDevicesContext";
useMediaDevices,
type MediaDevices,
} from "../livekit/MediaDevicesContext";
import { useMatrixRTCSessionMemberships } from "../useMatrixRTCSessionMemberships"; import { useMatrixRTCSessionMemberships } from "../useMatrixRTCSessionMemberships";
import { enterRTCSession, leaveRTCSession } from "../rtcSessionHelpers"; import { enterRTCSession, leaveRTCSession } from "../rtcSessionHelpers";
import { useRoomEncryptionSystem } from "../e2ee/sharedKeyManagement"; import { useRoomEncryptionSystem } from "../e2ee/sharedKeyManagement";
@@ -154,12 +144,8 @@ export const GroupCallView: FC<Props> = ({
); );
const deviceContext = useMediaDevices(); const deviceContext = useMediaDevices();
const latestDevices = useRef<MediaDevices | undefined>(undefined); const latestDevices = useLatest(deviceContext);
latestDevices.current = deviceContext; const latestMuteStates = useLatest(muteStates);
// TODO: why do we use a ref here instead of using muteStates directly?
const latestMuteStates = useRef<MuteStates | undefined>(undefined);
latestMuteStates.current = muteStates;
useEffect(() => { useEffect(() => {
const defaultDeviceSetup = async ({ const defaultDeviceSetup = async ({
@@ -232,7 +218,15 @@ export const GroupCallView: FC<Props> = ({
void enterRTCSession(rtcSession, perParticipantE2EE); void enterRTCSession(rtcSession, perParticipantE2EE);
} }
} }
}, [widget, rtcSession, preload, skipLobby, perParticipantE2EE]); }, [
widget,
rtcSession,
preload,
skipLobby,
perParticipantE2EE,
latestDevices,
latestMuteStates,
]);
const [left, setLeft] = useState(false); const [left, setLeft] = useState(false);
const [leaveError, setLeaveError] = useState<Error | undefined>(undefined); const [leaveError, setLeaveError] = useState<Error | undefined>(undefined);

View File

@@ -8,12 +8,13 @@ Please see LICENSE in the repository root for full details.
import { type RefObject, useRef } from "react"; import { type RefObject, useRef } from "react";
export interface LatestRef<T> extends RefObject<T> { export interface LatestRef<T> extends RefObject<T> {
current: T; current: T; // Always defined, unlike RefObject["current"]
} }
/** /**
* React hook that returns a ref containing the value given on the latest * React hook that returns a ref containing the value given on the latest
* render. * render. Useful for accessing the latest value of something in an effect or
* callback when you don't want reactivity.
*/ */
export function useLatest<T>(value: T): LatestRef<T> { export function useLatest<T>(value: T): LatestRef<T> {
const ref = useRef<T>(value); const ref = useRef<T>(value);