Skip to content

Commit 85cc017

Browse files
authored
DevTools: Add support for useOptimistic Hook (#27982)
## Summary Add support for `useOptimistic` Hook fixing "Unsupported hook in the react-debug-tools package: Missing method in Dispatcher: useOptimistic" when inspecting components using `useOptimistic` ## How did you test this change? - Added test following the same pattern as for `useDeferredValue`
1 parent 00f9acb commit 85cc017

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

packages/react-debug-tools/src/ReactDebugHooks.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ function getPrimitiveStackCache(): Map<string, Array<any>> {
8080
// This type check is for Flow only.
8181
Dispatcher.useMemoCache(0);
8282
}
83+
84+
if (typeof Dispatcher.useOptimistic === 'function') {
85+
// This type check is for Flow only.
86+
Dispatcher.useOptimistic(null, (s: mixed, a: mixed) => s);
87+
}
8388
} finally {
8489
readHookLog = hookLog;
8590
hookLog = [];
@@ -348,6 +353,25 @@ function useMemoCache(size: number): Array<any> {
348353
return data;
349354
}
350355

356+
function useOptimistic<S, A>(
357+
passthrough: S,
358+
reducer: ?(S, A) => S,
359+
): [S, (A) => void] {
360+
const hook = nextHook();
361+
let state;
362+
if (hook !== null) {
363+
state = hook.memoizedState;
364+
} else {
365+
state = passthrough;
366+
}
367+
hookLog.push({
368+
primitive: 'Optimistic',
369+
stackError: new Error(),
370+
value: state,
371+
});
372+
return [state, (action: A) => {}];
373+
}
374+
351375
const Dispatcher: DispatcherType = {
352376
use,
353377
readContext,
@@ -361,6 +385,7 @@ const Dispatcher: DispatcherType = {
361385
useInsertionEffect,
362386
useMemo,
363387
useMemoCache,
388+
useOptimistic,
364389
useReducer,
365390
useRef,
366391
useState,

packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,4 +1106,42 @@ describe('ReactHooksInspectionIntegration', () => {
11061106
},
11071107
]);
11081108
});
1109+
1110+
// @gate enableAsyncActions
1111+
it('should support useOptimistic hook', () => {
1112+
const useOptimistic = React.useOptimistic;
1113+
function Foo() {
1114+
const [value] = useOptimistic('abc', currentState => currentState);
1115+
React.useMemo(() => 'memo', []);
1116+
React.useMemo(() => 'not used', []);
1117+
return value;
1118+
}
1119+
1120+
const renderer = ReactTestRenderer.create(<Foo />);
1121+
const childFiber = renderer.root.findByType(Foo)._currentFiber();
1122+
const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);
1123+
expect(tree).toEqual([
1124+
{
1125+
id: 0,
1126+
isStateEditable: false,
1127+
name: 'Optimistic',
1128+
value: 'abc',
1129+
subHooks: [],
1130+
},
1131+
{
1132+
id: 1,
1133+
isStateEditable: false,
1134+
name: 'Memo',
1135+
value: 'memo',
1136+
subHooks: [],
1137+
},
1138+
{
1139+
id: 2,
1140+
isStateEditable: false,
1141+
name: 'Memo',
1142+
value: 'not used',
1143+
subHooks: [],
1144+
},
1145+
]);
1146+
});
11091147
});

packages/react-devtools-shell/src/app/InspectableElements/CustomHooks.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
useContext,
1818
useDebugValue,
1919
useEffect,
20+
useOptimistic,
2021
useState,
2122
} from 'react';
2223

@@ -73,6 +74,7 @@ function FunctionWithHooks(props: any, ref: React$Ref<any>) {
7374
const [count, updateCount] = useState(0);
7475
// eslint-disable-next-line no-unused-vars
7576
const contextValueA = useContext(ContextA);
77+
useOptimistic<number, mixed>(1);
7678

7779
// eslint-disable-next-line no-unused-vars
7880
const [_, __] = useState(object);

0 commit comments

Comments
 (0)