diff --git a/res/css/views/avatars/_DecoratedRoomAvatar.scss b/res/css/views/avatars/_DecoratedRoomAvatar.scss
index e0afd9de66..2631cbfb40 100644
--- a/res/css/views/avatars/_DecoratedRoomAvatar.scss
+++ b/res/css/views/avatars/_DecoratedRoomAvatar.scss
@@ -14,8 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// XXX: We shouldn't be using TemporaryTile anywhere - delete it.
-.mx_DecoratedRoomAvatar, .mx_TemporaryTile {
+.mx_DecoratedRoomAvatar, .mx_ExtraTile {
     position: relative;
 
     &.mx_DecoratedRoomAvatar_cutout .mx_BaseAvatar {
diff --git a/src/components/views/rooms/TemporaryTile.tsx b/src/components/views/rooms/ExtraTile.tsx
similarity index 92%
rename from src/components/views/rooms/TemporaryTile.tsx
rename to src/components/views/rooms/ExtraTile.tsx
index 31d2acbc61..20d12955d5 100644
--- a/src/components/views/rooms/TemporaryTile.tsx
+++ b/src/components/views/rooms/ExtraTile.tsx
@@ -1,5 +1,5 @@
 /*
-Copyright 2020 The Matrix.org Foundation C.I.C.
+Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -36,8 +36,7 @@ interface IState {
     hover: boolean;
 }
 
-// TODO: Remove with community invites in the room list: https://github.com/vector-im/element-web/issues/14456
-export default class TemporaryTile extends React.Component<IProps, IState> {
+export default class ExtraTile extends React.Component<IProps, IState> {
     constructor(props: IProps) {
         super(props);
 
@@ -57,8 +56,8 @@ export default class TemporaryTile extends React.Component<IProps, IState> {
     public render(): React.ReactElement {
         // XXX: We copy classes because it's easier
         const classes = classNames({
+            'mx_ExtraTile': true,
             'mx_RoomTile': true,
-            'mx_TemporaryTile': true,
             'mx_RoomTile_selected': this.props.isSelected,
             'mx_RoomTile_minimized': this.props.isMinimized,
         });
diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx
index beb85e50ce..7b44647be6 100644
--- a/src/components/views/rooms/RoomList.tsx
+++ b/src/components/views/rooms/RoomList.tsx
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-import * as React from "react";
+import React, { ReactComponentElement } from "react";
 import { Dispatcher } from "flux";
 import { Room } from "matrix-js-sdk/src/models/room";
 import * as fbEmitter from "fbemitter";
@@ -34,7 +34,7 @@ import RoomSublist from "./RoomSublist";
 import { ActionPayload } from "../../../dispatcher/payloads";
 import { MatrixClientPeg } from "../../../MatrixClientPeg";
 import GroupAvatar from "../avatars/GroupAvatar";
-import TemporaryTile from "./TemporaryTile";
+import ExtraTile from "./ExtraTile";
 import { StaticNotificationState } from "../../../stores/notifications/StaticNotificationState";
 import { NotificationColor } from "../../../stores/notifications/NotificationColor";
 import { Action } from "../../../dispatcher/actions";
@@ -422,7 +422,7 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
         dis.dispatch({ action: Action.ViewRoomDirectory, initialText });
     };
 
-    private renderSuggestedRooms(): JSX.Element[] {
+    private renderSuggestedRooms(): ReactComponentElement<typeof ExtraTile>[] {
         return this.state.suggestedRooms.map(room => {
             const name = room.name || room.canonical_alias || room.aliases.pop() || _t("Empty room");
             const avatar = (
@@ -443,7 +443,7 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
                 });
             };
             return (
-                <TemporaryTile
+                <ExtraTile
                     isMinimized={this.props.isMinimized}
                     isSelected={this.state.currentRoomId === room.room_id}
                     displayName={name}
@@ -455,7 +455,7 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
         });
     }
 
-    private renderCommunityInvites(): TemporaryTile[] {
+    private renderCommunityInvites(): ReactComponentElement<typeof ExtraTile>[] {
         // TODO: Put community invites in a more sensible place (not in the room list)
         // See https://github.com/vector-im/element-web/issues/14456
         return MatrixClientPeg.get().getGroups().filter(g => {
@@ -476,7 +476,7 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
                 });
             };
             return (
-                <TemporaryTile
+                <ExtraTile
                     isMinimized={this.props.isMinimized}
                     isSelected={false}
                     displayName={g.name}
@@ -538,7 +538,7 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
                 isMinimized={this.props.isMinimized}
                 onResize={this.props.onResize}
                 showSkeleton={showSkeleton}
-                extraBadTilesThatShouldntExist={extraTiles}
+                extraTiles={extraTiles}
             />);
         }
 
diff --git a/src/components/views/rooms/RoomSublist.tsx b/src/components/views/rooms/RoomSublist.tsx
index a2574bf60c..1a9ff182bc 100644
--- a/src/components/views/rooms/RoomSublist.tsx
+++ b/src/components/views/rooms/RoomSublist.tsx
@@ -17,7 +17,7 @@ limitations under the License.
 */
 
 import * as React from "react";
-import {createRef} from "react";
+import { createRef, ReactComponentElement } from "react";
 import { Room } from "matrix-js-sdk/src/models/room";
 import classNames from 'classnames';
 import { RovingAccessibleButton, RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex";
@@ -48,7 +48,7 @@ import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNo
 import RoomListLayoutStore from "../../../stores/room-list/RoomListLayoutStore";
 import { arrayFastClone, arrayHasOrderChange } from "../../../utils/arrays";
 import { objectExcluding, objectHasDiff } from "../../../utils/objects";
-import TemporaryTile from "./TemporaryTile";
+import ExtraTile from "./ExtraTile";
 import { ListNotificationState } from "../../../stores/notifications/ListNotificationState";
 import IconizedContextMenu from "../context_menus/IconizedContextMenu";
 
@@ -73,9 +73,7 @@ interface IProps {
     onResize: () => void;
     showSkeleton?: boolean;
 
-    // TODO: Don't use this. It's for community invites, and community invites shouldn't be here.
-    // You should feel bad if you use this.
-    extraBadTilesThatShouldntExist?: TemporaryTile[];
+    extraTiles?: ReactComponentElement<typeof ExtraTile>[];
 
     // TODO: Account for https://github.com/vector-im/element-web/issues/14179
 }
@@ -95,7 +93,7 @@ interface IState {
     isExpanded: boolean; // used for the for expand of the sublist when the room list is being filtered
     height: number;
     rooms: Room[];
-    filteredExtraTiles?: TemporaryTile[];
+    filteredExtraTiles?: ReactComponentElement<typeof ExtraTile>[];
 }
 
 export default class RoomSublist extends React.Component<IProps, IState> {
@@ -153,12 +151,12 @@ export default class RoomSublist extends React.Component<IProps, IState> {
         return padding;
     }
 
-    private get extraTiles(): TemporaryTile[] | null {
+    private get extraTiles(): ReactComponentElement<typeof ExtraTile>[] | null {
         if (this.state.filteredExtraTiles) {
             return this.state.filteredExtraTiles;
         }
-        if (this.props.extraBadTilesThatShouldntExist) {
-            return this.props.extraBadTilesThatShouldntExist;
+        if (this.props.extraTiles) {
+            return this.props.extraTiles;
         }
         return null;
     }
@@ -177,7 +175,7 @@ export default class RoomSublist extends React.Component<IProps, IState> {
     }
 
     public componentDidUpdate(prevProps: Readonly<IProps>, prevState: Readonly<IState>) {
-        const prevExtraTiles = prevState.filteredExtraTiles || prevProps.extraBadTilesThatShouldntExist;
+        const prevExtraTiles = prevState.filteredExtraTiles || prevProps.extraTiles;
         // as the rooms can come in one by one we need to reevaluate
         // the amount of available rooms to cap the amount of requested visible rooms by the layout
         if (RoomSublist.calcNumTiles(prevState.rooms, prevExtraTiles) !== this.numTiles) {
@@ -200,8 +198,8 @@ export default class RoomSublist extends React.Component<IProps, IState> {
 
         // If we're supposed to handle extra tiles, take the performance hit and re-render all the
         // time so we don't have to consider them as part of the visible room optimization.
-        const prevExtraTiles = this.props.extraBadTilesThatShouldntExist || [];
-        const nextExtraTiles = (nextState.filteredExtraTiles || nextProps.extraBadTilesThatShouldntExist) || [];
+        const prevExtraTiles = this.props.extraTiles || [];
+        const nextExtraTiles = (nextState.filteredExtraTiles || nextProps.extraTiles) || [];
         if (prevExtraTiles.length > 0 || nextExtraTiles.length > 0) {
             return true;
         }
@@ -249,10 +247,10 @@ export default class RoomSublist extends React.Component<IProps, IState> {
     private onListsUpdated = () => {
         const stateUpdates: IState & any = {}; // &any is to avoid a cast on the initializer
 
-        if (this.props.extraBadTilesThatShouldntExist) {
+        if (this.props.extraTiles) {
             const nameCondition = RoomListStore.instance.getFirstNameFilterCondition();
             if (nameCondition) {
-                stateUpdates.filteredExtraTiles = this.props.extraBadTilesThatShouldntExist
+                stateUpdates.filteredExtraTiles = this.props.extraTiles
                     .filter(t => nameCondition.matches(t.props.displayName || ""));
             } else if (this.state.filteredExtraTiles) {
                 stateUpdates.filteredExtraTiles = null;