Skip to content

Commit 13c9c18

Browse files
committed
fix: do not clear dialog state immediately on useDialog unmount
1 parent 56def19 commit 13c9c18

File tree

4 files changed

+59
-6
lines changed

4 files changed

+59
-6
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@
257257
"react-dom": "^18.1.0",
258258
"react-test-renderer": "^18.1.0",
259259
"semantic-release": "^19.0.5",
260-
"stream-chat": "^8.46.1",
260+
"stream-chat": "^8.47.1",
261261
"ts-jest": "^29.1.4",
262262
"typescript": "^5.4.5"
263263
},

src/components/Dialog/DialogManager.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export type Dialog = {
1111
id: DialogId;
1212
isOpen: boolean | undefined;
1313
open: (zIndex?: number) => void;
14+
removalTimeout: NodeJS.Timeout | undefined;
1415
remove: () => void;
1516
toggle: (closeAll?: boolean) => void;
1617
};
@@ -64,6 +65,7 @@ export class DialogManager {
6465
open: () => {
6566
this.open({ id });
6667
},
68+
removalTimeout: undefined,
6769
remove: () => {
6870
this.remove(id);
6971
},
@@ -76,6 +78,23 @@ export class DialogManager {
7678
...{ dialogsById: { ...current.dialogsById, [id]: dialog } },
7779
}));
7880
}
81+
82+
if (dialog.removalTimeout) {
83+
clearTimeout(dialog.removalTimeout);
84+
this.state.next((current) => ({
85+
...current,
86+
...{
87+
dialogsById: {
88+
...current.dialogsById,
89+
[id]: {
90+
...dialog,
91+
removalTimeout: undefined,
92+
},
93+
},
94+
},
95+
}));
96+
}
97+
7998
return dialog;
8099
}
81100

@@ -117,6 +136,10 @@ export class DialogManager {
117136
const dialog = state.dialogsById[id];
118137
if (!dialog) return;
119138

139+
if (dialog.removalTimeout) {
140+
clearTimeout(dialog.removalTimeout);
141+
}
142+
120143
this.state.next((current) => {
121144
const newDialogs = { ...current.dialogsById };
122145
delete newDialogs[id];
@@ -126,4 +149,30 @@ export class DialogManager {
126149
};
127150
});
128151
}
152+
153+
/**
154+
* Marks the dialog state as unused. If the dialog id is referenced again quickly,
155+
* the state will not be removed. Otherwise, the state will be removed after
156+
* a short timeout.
157+
*/
158+
markForRemoval(id: DialogId) {
159+
const dialog = this.state.getLatestValue().dialogsById[id];
160+
161+
if (!dialog) {
162+
return;
163+
}
164+
165+
this.state.next((current) => ({
166+
...current,
167+
dialogsById: {
168+
...current.dialogsById,
169+
[id]: {
170+
...dialog,
171+
removalTimeout: setTimeout(() => {
172+
this.remove(id);
173+
}, 16),
174+
},
175+
},
176+
}));
177+
}
129178
}

src/components/Dialog/hooks/useDialog.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ export const useDialog = ({ id }: GetOrCreateDialogParams) => {
99

1010
useEffect(
1111
() => () => {
12-
dialogManager.remove(id);
12+
// Since this cleanup can run even if the component is still mounted
13+
// and dialog id is unchanged (e.g. in <StrictMode />), it's safer to
14+
// mark state as unused and only remove it after a timeout, rather than
15+
// to remove it immediately.
16+
dialogManager.markForRemoval(id);
1317
},
1418
[dialogManager, id],
1519
);

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12231,10 +12231,10 @@ [email protected]:
1223112231
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
1223212232
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
1223312233

12234-
stream-chat@^8.46.1:
12235-
version "8.46.1"
12236-
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-8.46.1.tgz#9624bbd4e8e357414389e4b0dcb5f0134487f679"
12237-
integrity sha512-jVg148tZDCAmZa6b31cnamiUvt58IQB4YTRIGFt3+4zp6jI2tKeHvEj24uEcVF2d7fhT1IXSuGhNfcrStqSZHQ==
12234+
stream-chat@^8.47.1:
12235+
version "8.47.1"
12236+
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-8.47.1.tgz#5390c87cbb1929e7ca183aa1204dae3ab38469a2"
12237+
integrity sha512-raMAGYLT4UCVluMF0TMfdPKH9OUhDjH6e1HQdJIlllAFLaA8oxtG+e/7jyuPmVodLPzYCPqOt2eBH7soAkhV/A==
1223812238
dependencies:
1223912239
"@babel/runtime" "^7.16.3"
1224012240
"@types/jsonwebtoken" "~9.0.0"

0 commit comments

Comments
 (0)