Skip to content

Commit 41e9c17

Browse files
authored
fix[devtools]: allow element updates polling only if bridge is alive (#27067)
When some element is inspected in DevTools, we have a polling which updates the data for this element. Sometimes when service worker dies or bridge is getting shutdown, we continue to poll this data and will spam with the same "timed out error". <img width="1728" alt="Screenshot 2023-07-28 at 17 39 23" src="https://github.com/facebook/react/assets/28902667/220c4504-1ccc-4e87-9d78-bfff8b708230"> These changes add an explicit check that polling is allowed only while bridge is alive.
1 parent 2c4c847 commit 41e9c17

File tree

2 files changed

+42
-25
lines changed

2 files changed

+42
-25
lines changed

packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContext.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ export function InspectedElementContextController({
107107
parseHookNamesByDefault || alreadyLoadedHookNames,
108108
);
109109

110+
const [bridgeIsAlive, setBridgeIsAliveStatus] = useState<boolean>(true);
111+
110112
const elementHasChanged = element !== null && element !== state.element;
111113

112114
// Reset the cached inspected paths when a new element is selected.
@@ -213,14 +215,25 @@ export function InspectedElementContextController({
213215
}
214216
}, [state]);
215217

218+
useEffect(() => {
219+
// Assuming that new bridge is always alive at this moment
220+
setBridgeIsAliveStatus(true);
221+
222+
const listener = () => setBridgeIsAliveStatus(false);
223+
bridge.addListener('shutdown', listener);
224+
225+
return () => bridge.removeListener('shutdown', listener);
226+
}, [bridge]);
227+
216228
// Periodically poll the selected element for updates.
217229
useEffect(() => {
218-
if (element !== null) {
230+
if (element !== null && bridgeIsAlive) {
219231
const checkForUpdateWrapper = () => {
220232
checkForUpdate({bridge, element, refresh, store});
221233
timeoutID = setTimeout(checkForUpdateWrapper, POLL_INTERVAL);
222234
};
223235
let timeoutID = setTimeout(checkForUpdateWrapper, POLL_INTERVAL);
236+
224237
return () => {
225238
clearTimeout(timeoutID);
226239
};
@@ -232,6 +245,7 @@ export function InspectedElementContextController({
232245
// No sense to ping right away after e.g. inspecting/hydrating a path.
233246
inspectedElement,
234247
state,
248+
bridgeIsAlive,
235249
]);
236250

237251
const value = useMemo<Context>(

packages/react-devtools-shared/src/inspectedElementCache.js

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -180,32 +180,35 @@ export function checkForUpdate({
180180
}): void {
181181
const {id} = element;
182182
const rendererID = store.getRendererIDForElement(id);
183-
if (rendererID != null) {
184-
inspectElementMutableSource({
185-
bridge,
186-
element,
187-
path: null,
188-
rendererID: ((rendererID: any): number),
189-
}).then(
190-
([inspectedElement, responseType]: [
191-
InspectedElementFrontend,
192-
InspectedElementResponseType,
193-
]) => {
194-
if (responseType === 'full-data') {
195-
startTransition(() => {
196-
const [key, value] = createCacheSeed(element, inspectedElement);
197-
refresh(key, value);
198-
});
199-
}
200-
},
201183

202-
// There isn't much to do about errors in this case,
203-
// but we should at least log them so they aren't silent.
204-
error => {
205-
console.error(error);
206-
},
207-
);
184+
if (rendererID == null) {
185+
return;
208186
}
187+
188+
inspectElementMutableSource({
189+
bridge,
190+
element,
191+
path: null,
192+
rendererID,
193+
}).then(
194+
([inspectedElement, responseType]: [
195+
InspectedElementFrontend,
196+
InspectedElementResponseType,
197+
]) => {
198+
if (responseType === 'full-data') {
199+
startTransition(() => {
200+
const [key, value] = createCacheSeed(element, inspectedElement);
201+
refresh(key, value);
202+
});
203+
}
204+
},
205+
206+
// There isn't much to do about errors in this case,
207+
// but we should at least log them so they aren't silent.
208+
error => {
209+
console.error(error);
210+
},
211+
);
209212
}
210213

211214
export function clearCacheBecauseOfError(refresh: RefreshFunction): void {

0 commit comments

Comments
 (0)