Add useSyncExternalStore to react-debug-tools (#22240)
Adds support for useSyncExternalStore to react-debug-tools, which in turn adds support for React Devtools. Test plan: I added a test to ReactHooksInspectionIntegration, based on existing one for useMutableSource.
Andrew Clark committed
Sep 7, 2021 at 13:58 UTC
cfd81933286f3a63734ba0ac1650019487c402ff
2 files changed
+46
-1
packages/react-debug-tools/src/ReactDebugHooks.js
+13
-1
@@ -269,7 +269,19 @@ function useSyncExternalStore<T>(
269
subscribe: (() => void) => () => void,
270
getSnapshot: () => T,
271
): T {
272
- throw new Error('Not yet implemented');
272
+ // useSyncExternalStore() composes multiple hooks internally.
273
+ // Advance the current hook index the same number of times
274
+ // so that subsequent hooks have the right memoized state.
275
+ nextHook(); // SyncExternalStore
276
+ nextHook(); // LayoutEffect
277
+ nextHook(); // Effect
278
+ const value = getSnapshot();
279
+ hookLog.push({
280
+ primitive: 'SyncExternalStore',
281
+ stackError: new Error(),
282
+ value,
283
+ });
284
+ return value;
285
}
286
287
function useTransition(): [boolean, (() => void) => void] {
packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js
+33
@@ -878,4 +878,37 @@ describe('ReactHooksInspectionIntegration', () => {
878
},
879
]);
880
});
881
+
882
+ // @gate experimental || www
883
+ it('should support composite useSyncExternalStore hook', () => {
884
+ const useSyncExternalStore = React.unstable_useSyncExternalStore;
885
+ function Foo() {
886
+ const value = useSyncExternalStore(
887
+ () => () => {},
888
+ () => 'snapshot',
889
+ );
890
+ React.useMemo(() => 'memo', []);
891
+ return value;
892
+ }
893
+
894
+ const renderer = ReactTestRenderer.create(<Foo />);
895
+ const childFiber = renderer.root.findByType(Foo)._currentFiber();
896
+ const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);
897
+ expect(tree).toEqual([
898
+ {
899
+ id: 0,
900
+ isStateEditable: false,
901
+ name: 'SyncExternalStore',
902
+ value: 'snapshot',
903
+ subHooks: [],
904
+ },
905
+ {
906
+ id: 1,
907
+ isStateEditable: false,
908
+ name: 'Memo',
909
+ value: 'memo',
910
+ subHooks: [],
911
+ },
912
+ ]);
913
+ });
914
});