mirror of
https://github.com/vector-im/element-web.git
synced 2026-05-05 04:06:44 +02:00
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:
parent
0053bedc38
commit
7c3cf696fd
@ -158,9 +158,9 @@ export function useRoomSummaryCardViewModel(
|
||||
const e2eStatus = roomContext.e2eStatus;
|
||||
const isVideoRoom = calcIsVideoRoom(room);
|
||||
|
||||
const roomState = useRoomState(room);
|
||||
// used to check if the room is public or not
|
||||
const roomJoinRule = roomState.getJoinRule();
|
||||
const { roomJoinRule } = useRoomState(room, (state) => ({
|
||||
roomJoinRule: state.getJoinRule(),
|
||||
}));
|
||||
const alias = room.getCanonicalAlias() || room.getAltAliases()[0] || "";
|
||||
const pinCount = usePinnedEvents(room).length;
|
||||
// value to check if the user can invite to the room
|
||||
|
||||
@ -12,14 +12,32 @@ import { type Room, type RoomState, RoomStateEvent } from "matrix-js-sdk/src/mat
|
||||
import { useTypedEventEmitter } from "./useEventEmitter";
|
||||
|
||||
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
|
||||
export const useRoomState = <T extends any = RoomState>(
|
||||
room?: Room,
|
||||
mapper: Mapper<T> = defaultMapper as Mapper<T>,
|
||||
): T => {
|
||||
/**
|
||||
* A hook to watch the state of a room.
|
||||
*
|
||||
* Call `useRoomState` in a component to watch the state of a room.
|
||||
*
|
||||
* 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
|
||||
const savedMapper = useRef(mapper);
|
||||
|
||||
@ -28,7 +46,7 @@ export const useRoomState = <T extends any = RoomState>(
|
||||
savedMapper.current = 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(() => {
|
||||
if (!room) return;
|
||||
@ -39,8 +57,8 @@ export const useRoomState = <T extends any = RoomState>(
|
||||
useEffect(() => {
|
||||
update();
|
||||
return () => {
|
||||
setValue(room ? savedMapper.current(room.currentState) : (undefined as T));
|
||||
setValue(room ? savedMapper.current(room.currentState) : undefined);
|
||||
};
|
||||
}, [room, update]);
|
||||
return value;
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user