Fix instances of setState calls after unmount

pull/21833/head
Michael Telatynski 2021-07-15 12:10:54 +01:00
parent e9d56d4f13
commit 7c3c04d340
4 changed files with 31 additions and 31 deletions

View File

@ -916,6 +916,7 @@ export default class RoomView extends React.Component<IProps, IState> {
// called when state.room is first initialised (either at initial load, // called when state.room is first initialised (either at initial load,
// after a successful peek, or after we join the room). // after a successful peek, or after we join the room).
private onRoomLoaded = (room: Room) => { private onRoomLoaded = (room: Room) => {
if (this.unmounted) return;
// Attach a widget store listener only when we get a room // Attach a widget store listener only when we get a room
WidgetLayoutStore.instance.on(WidgetLayoutStore.emissionForRoom(room), this.onWidgetLayoutChange); WidgetLayoutStore.instance.on(WidgetLayoutStore.emissionForRoom(room), this.onWidgetLayoutChange);
this.onWidgetLayoutChange(); // provoke an update this.onWidgetLayoutChange(); // provoke an update
@ -930,9 +931,9 @@ export default class RoomView extends React.Component<IProps, IState> {
}; };
private async calculateRecommendedVersion(room: Room) { private async calculateRecommendedVersion(room: Room) {
this.setState({ const upgradeRecommendation = await room.getRecommendedVersion();
upgradeRecommendation: await room.getRecommendedVersion(), if (this.unmounted) return;
}); this.setState({ upgradeRecommendation });
} }
private async loadMembersIfJoined(room: Room) { private async loadMembersIfJoined(room: Room) {
@ -1022,23 +1023,19 @@ export default class RoomView extends React.Component<IProps, IState> {
}; };
private async updateE2EStatus(room: Room) { private async updateE2EStatus(room: Room) {
if (!this.context.isRoomEncrypted(room.roomId)) { if (!this.context.isRoomEncrypted(room.roomId)) return;
return;
} // If crypto is not currently enabled, we aren't tracking devices at all,
if (!this.context.isCryptoEnabled()) { // so we don't know what the answer is. Let's error on the safe side and show
// If crypto is not currently enabled, we aren't tracking devices at all, // a warning for this case.
// so we don't know what the answer is. Let's error on the safe side and show let e2eStatus = E2EStatus.Warning;
// a warning for this case. if (this.context.isCryptoEnabled()) {
this.setState({ /* At this point, the user has encryption on and cross-signing on */
e2eStatus: E2EStatus.Warning, e2eStatus = await shieldStatusForRoom(this.context, room);
});
return;
} }
/* At this point, the user has encryption on and cross-signing on */ if (this.unmounted) return;
this.setState({ this.setState({ e2eStatus });
e2eStatus: await shieldStatusForRoom(this.context, room),
});
} }
private onAccountData = (event: MatrixEvent) => { private onAccountData = (event: MatrixEvent) => {

View File

@ -1051,6 +1051,8 @@ class TimelinePanel extends React.Component<IProps, IState> {
{ windowLimit: this.props.timelineCap }); { windowLimit: this.props.timelineCap });
const onLoaded = () => { const onLoaded = () => {
if (this.unmounted) return;
// clear the timeline min-height when // clear the timeline min-height when
// (re)loading the timeline // (re)loading the timeline
if (this.messagePanel.current) { if (this.messagePanel.current) {
@ -1092,6 +1094,8 @@ class TimelinePanel extends React.Component<IProps, IState> {
}; };
const onError = (error) => { const onError = (error) => {
if (this.unmounted) return;
this.setState({ timelineLoading: false }); this.setState({ timelineLoading: false });
console.error( console.error(
`Error loading timeline panel at ${eventId}: ${error}`, `Error loading timeline panel at ${eventId}: ${error}`,

View File

@ -38,7 +38,7 @@ interface IState {
@replaceableComponent("views.messages.SenderProfile") @replaceableComponent("views.messages.SenderProfile")
export default class SenderProfile extends React.Component<IProps, IState> { export default class SenderProfile extends React.Component<IProps, IState> {
static contextType = MatrixClientContext; static contextType = MatrixClientContext;
private unmounted: boolean; private unmounted = false;
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
@ -51,7 +51,6 @@ export default class SenderProfile extends React.Component<IProps, IState> {
} }
componentDidMount() { componentDidMount() {
this.unmounted = false;
this.updateRelatedGroups(); this.updateRelatedGroups();
if (this.state.userGroups.length === 0) { if (this.state.userGroups.length === 0) {
@ -67,30 +66,24 @@ export default class SenderProfile extends React.Component<IProps, IState> {
} }
private async getPublicisedGroups() { private async getPublicisedGroups() {
if (!this.unmounted) { const userGroups = await FlairStore.getPublicisedGroupsCached(this.context, this.props.mxEvent.getSender());
const userGroups = await FlairStore.getPublicisedGroupsCached( if (this.unmounted) return;
this.context, this.props.mxEvent.getSender(), this.setState({ userGroups });
);
this.setState({ userGroups });
}
} }
private onRoomStateEvents = (event: MatrixEvent) => { private onRoomStateEvents = (event: MatrixEvent) => {
if (event.getType() === 'm.room.related_groups' && if (event.getType() === 'm.room.related_groups' && event.getRoomId() === this.props.mxEvent.getRoomId()) {
event.getRoomId() === this.props.mxEvent.getRoomId()
) {
this.updateRelatedGroups(); this.updateRelatedGroups();
} }
}; };
private updateRelatedGroups() { private updateRelatedGroups() {
if (this.unmounted) return;
const room = this.context.getRoom(this.props.mxEvent.getRoomId()); const room = this.context.getRoom(this.props.mxEvent.getRoomId());
if (!room) return; if (!room) return;
const relatedGroupsEvent = room.currentState.getStateEvents('m.room.related_groups', ''); const relatedGroupsEvent = room.currentState.getStateEvents('m.room.related_groups', '');
this.setState({ this.setState({
relatedGroups: relatedGroupsEvent ? relatedGroupsEvent.getContent().groups || [] : [], relatedGroups: relatedGroupsEvent?.getContent().groups || [],
}); });
} }

View File

@ -76,6 +76,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
private readonly MESSAGE_PREVIEW_TEXT = _t("Hey you. You're the best!"); private readonly MESSAGE_PREVIEW_TEXT = _t("Hey you. You're the best!");
private themeTimer: number; private themeTimer: number;
private unmounted = false;
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
@ -101,6 +102,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();
const userId = client.getUserId(); const userId = client.getUserId();
const profileInfo = await client.getProfileInfo(userId); const profileInfo = await client.getProfileInfo(userId);
if (this.unmounted) return;
this.setState({ this.setState({
userId, userId,
@ -109,6 +111,10 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
}); });
} }
componentWillUnmount() {
this.unmounted = true;
}
private calculateThemeState(): IThemeState { private calculateThemeState(): IThemeState {
// We have to mirror the logic from ThemeWatcher.getEffectiveTheme so we // We have to mirror the logic from ThemeWatcher.getEffectiveTheme so we
// show the right values for things. // show the right values for things.