Fix instances of setState calls after unmount

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

View file

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

View file

@ -38,7 +38,7 @@ interface IState {
@replaceableComponent("views.messages.SenderProfile")
export default class SenderProfile extends React.Component<IProps, IState> {
static contextType = MatrixClientContext;
private unmounted: boolean;
private unmounted = false;
constructor(props: IProps) {
super(props);
@ -51,7 +51,6 @@ export default class SenderProfile extends React.Component<IProps, IState> {
}
componentDidMount() {
this.unmounted = false;
this.updateRelatedGroups();
if (this.state.userGroups.length === 0) {
@ -67,30 +66,24 @@ export default class SenderProfile extends React.Component<IProps, IState> {
}
private async getPublicisedGroups() {
if (!this.unmounted) {
const userGroups = await FlairStore.getPublicisedGroupsCached(
this.context, this.props.mxEvent.getSender(),
);
this.setState({ userGroups });
}
const userGroups = await FlairStore.getPublicisedGroupsCached(this.context, this.props.mxEvent.getSender());
if (this.unmounted) return;
this.setState({ userGroups });
}
private onRoomStateEvents = (event: MatrixEvent) => {
if (event.getType() === 'm.room.related_groups' &&
event.getRoomId() === this.props.mxEvent.getRoomId()
) {
if (event.getType() === 'm.room.related_groups' && event.getRoomId() === this.props.mxEvent.getRoomId()) {
this.updateRelatedGroups();
}
};
private updateRelatedGroups() {
if (this.unmounted) return;
const room = this.context.getRoom(this.props.mxEvent.getRoomId());
if (!room) return;
const relatedGroupsEvent = room.currentState.getStateEvents('m.room.related_groups', '');
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 themeTimer: number;
private unmounted = false;
constructor(props: IProps) {
super(props);
@ -101,6 +102,7 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
const client = MatrixClientPeg.get();
const userId = client.getUserId();
const profileInfo = await client.getProfileInfo(userId);
if (this.unmounted) return;
this.setState({
userId,
@ -109,6 +111,10 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
});
}
componentWillUnmount() {
this.unmounted = true;
}
private calculateThemeState(): IThemeState {
// We have to mirror the logic from ThemeWatcher.getEffectiveTheme so we
// show the right values for things.