mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
react-debug-tools accepts currentDispatcher ref as param (#14556)
* react-debug-tools accepts currentDispatcher ref as param * ReactDebugHooks injected dispatcher ref is optional
This commit is contained in:
@@ -20,7 +20,7 @@ import {
|
||||
ForwardRef,
|
||||
} from 'shared/ReactWorkTags';
|
||||
|
||||
const ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
|
||||
type CurrentDispatcherRef = typeof ReactSharedInternals.ReactCurrentDispatcher;
|
||||
|
||||
// Used to track hooks called during a render
|
||||
|
||||
@@ -408,10 +408,17 @@ function buildTree(rootStack, readHookLog): HooksTree {
|
||||
export function inspectHooks<Props>(
|
||||
renderFunction: Props => React$Node,
|
||||
props: Props,
|
||||
currentDispatcher: ?CurrentDispatcherRef,
|
||||
): HooksTree {
|
||||
let previousDispatcher = ReactCurrentDispatcher.current;
|
||||
// DevTools will pass the current renderer's injected dispatcher.
|
||||
// Other apps might compile debug hooks as part of their app though.
|
||||
if (currentDispatcher == null) {
|
||||
currentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
|
||||
}
|
||||
|
||||
let previousDispatcher = currentDispatcher.current;
|
||||
let readHookLog;
|
||||
ReactCurrentDispatcher.current = Dispatcher;
|
||||
currentDispatcher.current = Dispatcher;
|
||||
let ancestorStackError;
|
||||
try {
|
||||
ancestorStackError = new Error();
|
||||
@@ -419,7 +426,7 @@ export function inspectHooks<Props>(
|
||||
} finally {
|
||||
readHookLog = hookLog;
|
||||
hookLog = [];
|
||||
ReactCurrentDispatcher.current = previousDispatcher;
|
||||
currentDispatcher.current = previousDispatcher;
|
||||
}
|
||||
let rootStack = ErrorStackParser.parse(ancestorStackError);
|
||||
return buildTree(rootStack, readHookLog);
|
||||
@@ -450,10 +457,11 @@ function inspectHooksOfForwardRef<Props, Ref>(
|
||||
renderFunction: (Props, Ref) => React$Node,
|
||||
props: Props,
|
||||
ref: Ref,
|
||||
currentDispatcher: CurrentDispatcherRef,
|
||||
): HooksTree {
|
||||
let previousDispatcher = ReactCurrentDispatcher.current;
|
||||
let previousDispatcher = currentDispatcher.current;
|
||||
let readHookLog;
|
||||
ReactCurrentDispatcher.current = Dispatcher;
|
||||
currentDispatcher.current = Dispatcher;
|
||||
let ancestorStackError;
|
||||
try {
|
||||
ancestorStackError = new Error();
|
||||
@@ -461,7 +469,7 @@ function inspectHooksOfForwardRef<Props, Ref>(
|
||||
} finally {
|
||||
readHookLog = hookLog;
|
||||
hookLog = [];
|
||||
ReactCurrentDispatcher.current = previousDispatcher;
|
||||
currentDispatcher.current = previousDispatcher;
|
||||
}
|
||||
let rootStack = ErrorStackParser.parse(ancestorStackError);
|
||||
return buildTree(rootStack, readHookLog);
|
||||
@@ -482,7 +490,16 @@ function resolveDefaultProps(Component, baseProps) {
|
||||
return baseProps;
|
||||
}
|
||||
|
||||
export function inspectHooksOfFiber(fiber: Fiber) {
|
||||
export function inspectHooksOfFiber(
|
||||
fiber: Fiber,
|
||||
currentDispatcher: ?CurrentDispatcherRef,
|
||||
) {
|
||||
// DevTools will pass the current renderer's injected dispatcher.
|
||||
// Other apps might compile debug hooks as part of their app though.
|
||||
if (currentDispatcher == null) {
|
||||
currentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
|
||||
}
|
||||
|
||||
if (
|
||||
fiber.tag !== FunctionComponent &&
|
||||
fiber.tag !== SimpleMemoComponent &&
|
||||
@@ -506,9 +523,14 @@ export function inspectHooksOfFiber(fiber: Fiber) {
|
||||
try {
|
||||
setupContexts(contextMap, fiber);
|
||||
if (fiber.tag === ForwardRef) {
|
||||
return inspectHooksOfForwardRef(type.render, props, fiber.ref);
|
||||
return inspectHooksOfForwardRef(
|
||||
type.render,
|
||||
props,
|
||||
fiber.ref,
|
||||
currentDispatcher,
|
||||
);
|
||||
}
|
||||
return inspectHooks(type, props);
|
||||
return inspectHooks(type, props, currentDispatcher);
|
||||
} finally {
|
||||
currentHook = null;
|
||||
restoreContexts(contextMap);
|
||||
|
||||
@@ -216,4 +216,37 @@ describe('ReactHooksInspection', () => {
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should support an injected dispatcher', () => {
|
||||
function Foo(props) {
|
||||
let [state] = React.useState('hello world');
|
||||
return <div>{state}</div>;
|
||||
}
|
||||
|
||||
let initial = {};
|
||||
let current = initial;
|
||||
let getterCalls = 0;
|
||||
let setterCalls = [];
|
||||
let FakeDispatcherRef = {
|
||||
get current() {
|
||||
getterCalls++;
|
||||
return current;
|
||||
},
|
||||
set current(value) {
|
||||
setterCalls.push(value);
|
||||
current = value;
|
||||
},
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
ReactDebugTools.inspectHooks(Foo, {}, FakeDispatcherRef);
|
||||
}).toThrow(
|
||||
'Hooks can only be called inside the body of a function component.',
|
||||
);
|
||||
|
||||
expect(getterCalls).toBe(1);
|
||||
expect(setterCalls).toHaveLength(2);
|
||||
expect(setterCalls[0]).not.toBe(initial);
|
||||
expect(setterCalls[1]).toBe(initial);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -241,4 +241,39 @@ describe('ReactHooksInspectionIntergration', () => {
|
||||
let tree = ReactDebugTools.inspectHooksOfFiber(childFiber);
|
||||
expect(tree).toEqual([{name: 'State', value: 'def', subHooks: []}]);
|
||||
});
|
||||
|
||||
it('should support an injected dispatcher', () => {
|
||||
function Foo(props) {
|
||||
let [state] = React.useState('hello world');
|
||||
return <div>{state}</div>;
|
||||
}
|
||||
|
||||
let initial = {};
|
||||
let current = initial;
|
||||
let getterCalls = 0;
|
||||
let setterCalls = [];
|
||||
let FakeDispatcherRef = {
|
||||
get current() {
|
||||
getterCalls++;
|
||||
return current;
|
||||
},
|
||||
set current(value) {
|
||||
setterCalls.push(value);
|
||||
current = value;
|
||||
},
|
||||
};
|
||||
|
||||
let renderer = ReactTestRenderer.create(<Foo />);
|
||||
let childFiber = renderer.root._currentFiber();
|
||||
expect(() => {
|
||||
ReactDebugTools.inspectHooksOfFiber(childFiber, FakeDispatcherRef);
|
||||
}).toThrow(
|
||||
'Hooks can only be called inside the body of a function component.',
|
||||
);
|
||||
|
||||
expect(getterCalls).toBe(1);
|
||||
expect(setterCalls).toHaveLength(2);
|
||||
expect(setterCalls[0]).not.toBe(initial);
|
||||
expect(setterCalls[1]).toBe(initial);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user