Skip to content

Commit 8308d2f

Browse files
authored
fix[react-devtools/ReactDebugHooks]: support unstable prefixes in hooks and useContextWithBailout (#30837)
Related - #30407. This is experimental-only and FB-only hook. Without these changes, inspecting an element that is using this hook will throw an error, because this hook is missing in Dispatcher implementation from React DevTools, which overrides the original one to build the hook tree. ![Screenshot 2024-08-28 at 18 42 55](https://github.com/user-attachments/assets/e3bccb92-74fb-4e4a-8181-03d13f8512c0) One nice thing from it is that in case of any potential regressions related to this experiment, we can quickly triage which implementation of `useContext` is used by inspecting an element in React DevTools. Ideally, I should've added some component that is using this hook to `react-devtools-shell`, so it can be manually tested, but I can't do it without rewriting the infra for it. This is because this hook is only available from fb-www builds, and not experimental.
1 parent 394e75d commit 8308d2f

File tree

1 file changed

+30
-1
lines changed

1 file changed

+30
-1
lines changed

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

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import type {
2020
Dependencies,
2121
Fiber,
2222
Dispatcher as DispatcherType,
23+
ContextDependencyWithSelect,
2324
} from 'react-reconciler/src/ReactInternalTypes';
2425
import type {TransitionStatus} from 'react-reconciler/src/ReactFiberConfig';
2526

@@ -37,7 +38,6 @@ import {
3738
REACT_CONTEXT_TYPE,
3839
} from 'shared/ReactSymbols';
3940
import hasOwnProperty from 'shared/hasOwnProperty';
40-
import type {ContextDependencyWithSelect} from '../../react-reconciler/src/ReactInternalTypes';
4141

4242
type CurrentDispatcherRef = typeof ReactSharedInternals;
4343

@@ -76,6 +76,13 @@ function getPrimitiveStackCache(): Map<string, Array<any>> {
7676
try {
7777
// Use all hooks here to add them to the hook log.
7878
Dispatcher.useContext(({_currentValue: null}: any));
79+
if (typeof Dispatcher.unstable_useContextWithBailout === 'function') {
80+
// This type check is for Flow only.
81+
Dispatcher.unstable_useContextWithBailout(
82+
({_currentValue: null}: any),
83+
null,
84+
);
85+
}
7986
Dispatcher.useState(null);
8087
Dispatcher.useReducer((s: mixed, a: mixed) => s, null);
8188
Dispatcher.useRef(null);
@@ -280,6 +287,22 @@ function useContext<T>(context: ReactContext<T>): T {
280287
return value;
281288
}
282289

290+
function unstable_useContextWithBailout<T>(
291+
context: ReactContext<T>,
292+
select: (T => Array<mixed>) | null,
293+
): T {
294+
const value = readContext(context);
295+
hookLog.push({
296+
displayName: context.displayName || null,
297+
primitive: 'ContextWithBailout',
298+
stackError: new Error(),
299+
value: value,
300+
debugInfo: null,
301+
dispatcherHookName: 'ContextWithBailout',
302+
});
303+
return value;
304+
}
305+
283306
function useState<S>(
284307
initialState: (() => S) | S,
285308
): [S, Dispatch<BasicStateAction<S>>] {
@@ -753,6 +776,7 @@ const Dispatcher: DispatcherType = {
753776
useCacheRefresh,
754777
useCallback,
755778
useContext,
779+
unstable_useContextWithBailout,
756780
useEffect,
757781
useImperativeHandle,
758782
useDebugValue,
@@ -954,6 +978,11 @@ function parseHookName(functionName: void | string): string {
954978
} else {
955979
startIndex += 1;
956980
}
981+
982+
if (functionName.slice(startIndex).startsWith('unstable_')) {
983+
startIndex += 'unstable_'.length;
984+
}
985+
957986
if (functionName.slice(startIndex, startIndex + 3) === 'use') {
958987
if (functionName.length - startIndex === 3) {
959988
return 'Use';

0 commit comments

Comments
 (0)