@samitouri / QOS-React-2 / commits / cfd8193328

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 });