diff --git a/react/features/filmstrip/components/web/Filmstrip.tsx b/react/features/filmstrip/components/web/Filmstrip.tsx index 4a268819110b..a4e57a4af6ae 100644 --- a/react/features/filmstrip/components/web/Filmstrip.tsx +++ b/react/features/filmstrip/components/web/Filmstrip.tsx @@ -996,6 +996,7 @@ class Filmstrip extends PureComponent { _filmstripWidth, _hasScroll, _isVerticalFilmstrip, + _remoteParticipants, _remoteParticipantsLength, _resizableFilmstrip, _rows, @@ -1020,7 +1021,7 @@ class Filmstrip extends PureComponent { height = { _filmstripHeight } initialScrollLeft = { 0 } initialScrollTop = { 0 } - itemData = {{ filmstripType }} + itemData = {{ filmstripType, remoteParticipants: _remoteParticipants }} itemKey = { this._gridItemKey } onItemsRendered = { this._onGridItemsRendered } overscanRowCount = { 1 } @@ -1039,6 +1040,7 @@ class Filmstrip extends PureComponent { itemCount: _remoteParticipantsLength, className: `filmstrip__videos remote-videos ${_resizableFilmstrip ? '' : 'height-transition'}`, height: _filmstripHeight, + itemData: { remoteParticipants: _remoteParticipants }, itemKey: this._listItemKey, itemSize: 0, onItemsRendered: this._onListItemsRendered, diff --git a/react/features/filmstrip/components/web/ThumbnailWrapper.tsx b/react/features/filmstrip/components/web/ThumbnailWrapper.tsx index 136477f71e7a..d1e139c8bb27 100644 --- a/react/features/filmstrip/components/web/ThumbnailWrapper.tsx +++ b/react/features/filmstrip/components/web/ThumbnailWrapper.tsx @@ -136,7 +136,7 @@ class ThumbnailWrapper extends Component { * @returns {IProps} */ function _mapStateToProps(state: IReduxState, ownProps: { columnIndex: number; - data: { filmstripType: string; }; index?: number; rowIndex: number; }) { + data: { filmstripType: string; remoteParticipants?: string[]; }; index?: number; rowIndex: number; }) { const _currentLayout = getCurrentLayout(state); const { remoteParticipants: remote } = state['features/filmstrip']; const activeParticipants = getActiveParticipantsIds(state); @@ -145,7 +145,16 @@ function _mapStateToProps(state: IReduxState, ownProps: { columnIndex: number; const filmstripType = ownProps.data?.filmstripType; const stageFilmstrip = filmstripType === FILMSTRIP_TYPE.STAGE; const sortedActiveParticipants = activeParticipants.sort(); - const remoteParticipants = stageFilmstrip ? sortedActiveParticipants : remote; + + // Use the remoteParticipants snapshot passed via itemData to ensure + // consistency with Filmstrip's itemKey functions, which reference + // the same array from the parent's render cycle. Reading directly + // from Redux could yield a newer array if the store updated between + // the parent render and this selector call, causing key/participant + // mismatches (wrong video shown in a tile). + const remoteParticipants = stageFilmstrip + ? sortedActiveParticipants + : (ownProps.data?.remoteParticipants ?? remote); const remoteParticipantsLength = remoteParticipants.length; const localId = getLocalParticipant(state)?.id;