Skip to content

Commit bec3596

Browse files
authored
Merge pull request #131 from Kitware/fix-picking-after-unmount
fix(Picking): guard against unmounted state
2 parents 02c9c68 + 4d03628 commit bec3596

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

src/core/Picking.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
import deletionRegistry from '../utils/DeletionRegistry';
1414
import useDebounce from '../utils/useDebounce';
1515
import useGetterRef from '../utils/useGetterRef';
16+
import { useIsMounted } from '../utils/useIsMounted';
1617
import useMount from '../utils/useMount';
1718
import useUnmount from '../utils/useUnmount';
1819
import {
@@ -136,6 +137,8 @@ export default forwardRef(function ViewPicking(props: PickingProps, fwdRef) {
136137
};
137138
});
138139

140+
const isMounted = useIsMounted();
141+
139142
// --- Props --- //
140143

141144
const {
@@ -152,12 +155,16 @@ export default forwardRef(function ViewPicking(props: PickingProps, fwdRef) {
152155

153156
const pickClosest = useCallback(
154157
(xp: number, yp: number, tolerance: number): PickResult[] => {
158+
if (!isMounted.current) return [];
159+
155160
const x1 = Math.floor(xp - tolerance);
156161
const y1 = Math.floor(yp - tolerance);
157162
const x2 = Math.ceil(xp + tolerance);
158163
const y2 = Math.ceil(yp + tolerance);
159164

160165
const selector = getSelector();
166+
if (selector.isDeleted()) return [];
167+
161168
const openGLRenderWindow = openGLRenderWindowAPI.get();
162169
const renderer = rendererAPI.get();
163170

@@ -218,12 +225,16 @@ export default forwardRef(function ViewPicking(props: PickingProps, fwdRef) {
218225
},
219226
] as PickResult[];
220227
},
221-
[rendererAPI, openGLRenderWindowAPI, getSelector]
228+
[rendererAPI, openGLRenderWindowAPI, isMounted, getSelector]
222229
);
223230

224231
const pick = useCallback(
225232
(x1: number, y1: number, x2: number, y2: number): PickResult[] => {
233+
if (!isMounted.current) return [];
234+
226235
const selector = getSelector();
236+
if (selector.isDeleted()) return [];
237+
227238
const openGLRenderWindow = openGLRenderWindowAPI.get();
228239
const renderer = rendererAPI.get();
229240

@@ -277,7 +288,7 @@ export default forwardRef(function ViewPicking(props: PickingProps, fwdRef) {
277288
})
278289
.filter(Boolean) as PickResult[];
279290
},
280-
[rendererAPI, openGLRenderWindowAPI, getSelector]
291+
[rendererAPI, openGLRenderWindowAPI, isMounted, getSelector]
281292
);
282293

283294
const pickWithFrustum = useCallback(
@@ -287,7 +298,11 @@ export default forwardRef(function ViewPicking(props: PickingProps, fwdRef) {
287298
x2: number,
288299
y2: number
289300
): FrustumPickResult | null => {
301+
if (!isMounted.current) return null;
302+
290303
const selector = getSelector();
304+
if (selector.isDeleted()) return null;
305+
291306
const openGLRenderWindow = openGLRenderWindowAPI.get();
292307
const renderer = rendererAPI.get();
293308

@@ -324,7 +339,7 @@ export default forwardRef(function ViewPicking(props: PickingProps, fwdRef) {
324339
});
325340
return { frustum, representationIds };
326341
},
327-
[rendererAPI, openGLRenderWindowAPI, getSelector]
342+
[rendererAPI, openGLRenderWindowAPI, isMounted, getSelector]
328343
);
329344

330345
const api = useMemo(

src/utils/useIsMounted.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { useRef } from 'react';
2+
import useMount from './useMount';
3+
import useUnmount from './useUnmount';
4+
5+
export function useIsMounted() {
6+
const isMounted = useRef(false);
7+
8+
useMount(() => {
9+
isMounted.current = true;
10+
});
11+
12+
useUnmount(() => {
13+
isMounted.current = false;
14+
});
15+
16+
return isMounted;
17+
}

0 commit comments

Comments
 (0)