@samitouri / QOS-React / commits / 00872e2e51

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 (