Fix failure to update room info panel on joinrule change (#31938)
* Fix failure to update room info panel on joinrule change Currently, if the join rules are updated, the room info panel is not updated until the panel is re-rendered. This is due to a misuse of `useRoomState`. * Update documentation and types on `useRoomState` This hook is useless without a `mapper` function, so let's mandate it. Also improve the documentation while we're here.
This commit is contained in:
@@ -158,9 +158,9 @@ export function useRoomSummaryCardViewModel(
|
|||||||
const e2eStatus = roomContext.e2eStatus;
|
const e2eStatus = roomContext.e2eStatus;
|
||||||
const isVideoRoom = calcIsVideoRoom(room);
|
const isVideoRoom = calcIsVideoRoom(room);
|
||||||
|
|
||||||
const roomState = useRoomState(room);
|
const { roomJoinRule } = useRoomState(room, (state) => ({
|
||||||
// used to check if the room is public or not
|
roomJoinRule: state.getJoinRule(),
|
||||||
const roomJoinRule = roomState.getJoinRule();
|
}));
|
||||||
const alias = room.getCanonicalAlias() || room.getAltAliases()[0] || "";
|
const alias = room.getCanonicalAlias() || room.getAltAliases()[0] || "";
|
||||||
const pinCount = usePinnedEvents(room).length;
|
const pinCount = usePinnedEvents(room).length;
|
||||||
// value to check if the user can invite to the room
|
// value to check if the user can invite to the room
|
||||||
|
|||||||
+28
-10
@@ -12,14 +12,32 @@ import { type Room, type RoomState, RoomStateEvent } from "matrix-js-sdk/src/mat
|
|||||||
import { useTypedEventEmitter } from "./useEventEmitter";
|
import { useTypedEventEmitter } from "./useEventEmitter";
|
||||||
|
|
||||||
type Mapper<T> = (roomState: RoomState) => T;
|
type Mapper<T> = (roomState: RoomState) => T;
|
||||||
const defaultMapper: Mapper<RoomState> = (roomState: RoomState) => roomState;
|
|
||||||
|
|
||||||
// Hook to simplify watching Matrix Room state
|
/**
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
|
* A hook to watch the state of a room.
|
||||||
export const useRoomState = <T extends any = RoomState>(
|
*
|
||||||
room?: Room,
|
* Call `useRoomState` in a component to watch the state of a room.
|
||||||
mapper: Mapper<T> = defaultMapper as Mapper<T>,
|
*
|
||||||
): T => {
|
* A mapper function must be provided to process the room state into outputs suitable for the component. The mapper
|
||||||
|
* function will be called whenever the room state changes.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* function MyComponent({room}: Props): JSX.Element {
|
||||||
|
* const { historyVisibility, joinRule } = useRoomState(room, state => ({
|
||||||
|
* historyVisibility: state.getHistoryVisibility(),
|
||||||
|
* joinRule: state.getJoinRule(),
|
||||||
|
* }));
|
||||||
|
* // ...
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param room - The room to watch. If this is undefined, the returned value will also be undefined.
|
||||||
|
* @param mapper - A function to process the room state into outputs suitable for the component.
|
||||||
|
* @returns The output of `mapper`, or `undefined` if `room` is undefined.
|
||||||
|
*/
|
||||||
|
export function useRoomState<T>(room: Room, mapper: Mapper<T>): T;
|
||||||
|
export function useRoomState<T>(room: Room | undefined, mapper: Mapper<T>): T | undefined;
|
||||||
|
export function useRoomState<T>(room: Room | undefined, mapper: Mapper<T>): T | undefined {
|
||||||
// Create a ref that stores mapper
|
// Create a ref that stores mapper
|
||||||
const savedMapper = useRef(mapper);
|
const savedMapper = useRef(mapper);
|
||||||
|
|
||||||
@@ -28,7 +46,7 @@ export const useRoomState = <T extends any = RoomState>(
|
|||||||
savedMapper.current = mapper;
|
savedMapper.current = mapper;
|
||||||
}, [mapper]);
|
}, [mapper]);
|
||||||
|
|
||||||
const [value, setValue] = useState<T>(room ? mapper(room.currentState) : (undefined as T));
|
const [value, setValue] = useState<T | undefined>(room ? mapper(room.currentState) : undefined);
|
||||||
|
|
||||||
const update = useCallback(() => {
|
const update = useCallback(() => {
|
||||||
if (!room) return;
|
if (!room) return;
|
||||||
@@ -39,8 +57,8 @@ export const useRoomState = <T extends any = RoomState>(
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
update();
|
update();
|
||||||
return () => {
|
return () => {
|
||||||
setValue(room ? savedMapper.current(room.currentState) : (undefined as T));
|
setValue(room ? savedMapper.current(room.currentState) : undefined);
|
||||||
};
|
};
|
||||||
}, [room, update]);
|
}, [room, update]);
|
||||||
return value;
|
return value;
|
||||||
};
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user