Fixed suspense fallback issue by moving inspection message side effect before suspending render
Brian Vaughn committed
Apr 22, 2019 at 15:25 UTC
00872e2e510daa4094fd24d7081528bf017474d0
1 file changed
+13
-9
src/devtools/views/Components/InspectedElementContext.js
+13
-9
@@ -59,7 +59,11 @@ type Props = {|
59
function InspectedElementContextController({ children }: Props) {
60
const bridge = useContext(BridgeContext);
61
const store = useContext(StoreContext);
62
- const { inspectedElementID } = useContext(TreeStateContext);
62
+
63
+ // It's very important that this context consumes selectedElementID and not inspectedElementID.
64
+ // Otherwise the effect that sends the "inspect" message across the bridge-
65
+ // would itself be blocked by the same render that suspends (waiting for the data).
66
+ const { selectedElementID } = useContext(TreeStateContext);
67
68
const [count, setCount] = useState<number>(0);
69
@@ -87,7 +91,7 @@ function InspectedElementContextController({ children }: Props) {
91
resource.write(id, inspectedElement);
92
93
// Schedule update with React if the curently-selected element has been invalidated.
90
- if (id === inspectedElementID) {
94
+ if (id === selectedElementID) {
95
setCount(count => count + 1);
96
}
97
}
@@ -96,22 +100,22 @@ function InspectedElementContextController({ children }: Props) {
100
101
bridge.addListener('inspectedElement', onInspectedElement);
102
return () => bridge.removeListener('inspectedElement', onInspectedElement);
99
- }, [bridge, inspectedElementID]);
103
+ }, [bridge, selectedElementID]);
104
105
// This effect handler polls for updates on the currently selected element.
106
useEffect(() => {
103
- if (inspectedElementID === null) {
107
+ if (selectedElementID === null) {
108
return () => {};
109
}
110
107
- const rendererID = store.getRendererIDForElement(inspectedElementID);
111
+ const rendererID = store.getRendererIDForElement(selectedElementID);
112
113
let timeoutID: TimeoutID | null = null;
114
115
const sendRequest = () => {
116
timeoutID = null;
117
114
- bridge.send('inspectElement', { id: inspectedElementID, rendererID });
118
+ bridge.send('inspectElement', { id: selectedElementID, rendererID });
119
};
120
121
// Send the initial inspection request.
@@ -121,7 +125,7 @@ function InspectedElementContextController({ children }: Props) {
125
const onInspectedElement = (inspectedElement: InspectedElement | null) => {
126
if (
127
inspectedElement !== null &&
124
- inspectedElement.id === inspectedElementID
128
+ inspectedElement.id === selectedElementID
129
) {
130
// If this is the element we requested, wait a little bit and then ask for an update.
131
timeoutID = setTimeout(sendRequest, 1000);
@@ -137,7 +141,7 @@ function InspectedElementContextController({ children }: Props) {
141
clearTimeout(timeoutID);
142
}
143
};
140
- }, [bridge, inspectedElementID, store]);
144
+ }, [bridge, selectedElementID, store]);
145
146
const value = useMemo(
147
() => ({
@@ -145,7 +149,7 @@ function InspectedElementContextController({ children }: Props) {
149
}),
150
// Count is used to invalidate the cache and schedule an update with React.
151
// eslint-disable-next-line react-hooks/exhaustive-deps
148
- [count, resource.read]
152
+ [count]
153
);
154
155
return (