[DevTools] Add support for useMemoCache (#26696)
useMemoCache wasn't previously supported in the DevTools, so any attempt to inspect a component using the hook would result in a `dispatcher.useMemoCache is not a function (it is undefined)` error.
This commit is contained in:
parent
ed545ae3d3
commit
25b99efe0c
|
@ -51,9 +51,19 @@ type Dispatch<A> = A => void;
|
||||||
|
|
||||||
let primitiveStackCache: null | Map<string, Array<any>> = null;
|
let primitiveStackCache: null | Map<string, Array<any>> = null;
|
||||||
|
|
||||||
|
type MemoCache = {
|
||||||
|
data: Array<Array<any>>,
|
||||||
|
index: number,
|
||||||
|
};
|
||||||
|
|
||||||
|
type FunctionComponentUpdateQueue = {
|
||||||
|
memoCache?: MemoCache | null,
|
||||||
|
};
|
||||||
|
|
||||||
type Hook = {
|
type Hook = {
|
||||||
memoizedState: any,
|
memoizedState: any,
|
||||||
next: Hook | null,
|
next: Hook | null,
|
||||||
|
updateQueue: FunctionComponentUpdateQueue | null,
|
||||||
};
|
};
|
||||||
|
|
||||||
function getPrimitiveStackCache(): Map<string, Array<any>> {
|
function getPrimitiveStackCache(): Map<string, Array<any>> {
|
||||||
|
@ -79,6 +89,10 @@ function getPrimitiveStackCache(): Map<string, Array<any>> {
|
||||||
Dispatcher.useDebugValue(null);
|
Dispatcher.useDebugValue(null);
|
||||||
Dispatcher.useCallback(() => {});
|
Dispatcher.useCallback(() => {});
|
||||||
Dispatcher.useMemo(() => null);
|
Dispatcher.useMemo(() => null);
|
||||||
|
if (typeof Dispatcher.useMemoCache === 'function') {
|
||||||
|
// This type check is for Flow only.
|
||||||
|
Dispatcher.useMemoCache(0);
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
readHookLog = hookLog;
|
readHookLog = hookLog;
|
||||||
hookLog = [];
|
hookLog = [];
|
||||||
|
@ -333,6 +347,38 @@ function useId(): string {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function useMemoCache(size: number): Array<any> {
|
||||||
|
const hook = nextHook();
|
||||||
|
let memoCache: MemoCache;
|
||||||
|
if (
|
||||||
|
hook !== null &&
|
||||||
|
hook.updateQueue !== null &&
|
||||||
|
hook.updateQueue.memoCache != null
|
||||||
|
) {
|
||||||
|
memoCache = hook.updateQueue.memoCache;
|
||||||
|
} else {
|
||||||
|
memoCache = {
|
||||||
|
data: [],
|
||||||
|
index: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = memoCache.data[memoCache.index];
|
||||||
|
if (data === undefined) {
|
||||||
|
const MEMO_CACHE_SENTINEL = Symbol.for('react.memo_cache_sentinel');
|
||||||
|
data = new Array(size);
|
||||||
|
for (let i = 0; i < size; i++) {
|
||||||
|
data[i] = MEMO_CACHE_SENTINEL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hookLog.push({
|
||||||
|
primitive: 'MemoCache',
|
||||||
|
stackError: new Error(),
|
||||||
|
value: data,
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
const Dispatcher: DispatcherType = {
|
const Dispatcher: DispatcherType = {
|
||||||
use,
|
use,
|
||||||
readContext,
|
readContext,
|
||||||
|
@ -345,6 +391,7 @@ const Dispatcher: DispatcherType = {
|
||||||
useLayoutEffect,
|
useLayoutEffect,
|
||||||
useInsertionEffect,
|
useInsertionEffect,
|
||||||
useMemo,
|
useMemo,
|
||||||
|
useMemoCache,
|
||||||
useReducer,
|
useReducer,
|
||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
|
|
|
@ -14,6 +14,7 @@ let React;
|
||||||
let ReactTestRenderer;
|
let ReactTestRenderer;
|
||||||
let ReactDebugTools;
|
let ReactDebugTools;
|
||||||
let act;
|
let act;
|
||||||
|
let useMemoCache;
|
||||||
|
|
||||||
describe('ReactHooksInspectionIntegration', () => {
|
describe('ReactHooksInspectionIntegration', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
@ -22,6 +23,7 @@ describe('ReactHooksInspectionIntegration', () => {
|
||||||
ReactTestRenderer = require('react-test-renderer');
|
ReactTestRenderer = require('react-test-renderer');
|
||||||
act = require('internal-test-utils').act;
|
act = require('internal-test-utils').act;
|
||||||
ReactDebugTools = require('react-debug-tools');
|
ReactDebugTools = require('react-debug-tools');
|
||||||
|
useMemoCache = React.unstable_useMemoCache;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should inspect the current state of useState hooks', async () => {
|
it('should inspect the current state of useState hooks', async () => {
|
||||||
|
@ -633,6 +635,33 @@ describe('ReactHooksInspectionIntegration', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// @gate enableUseMemoCacheHook
|
||||||
|
it('should support useMemoCache hook', () => {
|
||||||
|
function Foo() {
|
||||||
|
const $ = useMemoCache(1);
|
||||||
|
let t0;
|
||||||
|
|
||||||
|
if ($[0] === Symbol.for('react.memo_cache_sentinel')) {
|
||||||
|
t0 = <div>{1}</div>;
|
||||||
|
$[0] = t0;
|
||||||
|
} else {
|
||||||
|
t0 = $[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return t0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderer = ReactTestRenderer.create(<Foo />);
|
||||||
|
const childFiber = renderer.root.findByType(Foo)._currentFiber();
|
||||||
|
const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);
|
||||||
|
|
||||||
|
expect(tree.length).toEqual(1);
|
||||||
|
expect(tree[0].isStateEditable).toBe(false);
|
||||||
|
expect(tree[0].name).toBe('MemoCache');
|
||||||
|
expect(tree[0].value).toHaveLength(1);
|
||||||
|
expect(tree[0].value[0]).toEqual(<div>{1}</div>);
|
||||||
|
});
|
||||||
|
|
||||||
describe('useDebugValue', () => {
|
describe('useDebugValue', () => {
|
||||||
it('should support inspectable values for multiple custom hooks', () => {
|
it('should support inspectable values for multiple custom hooks', () => {
|
||||||
function useLabeledValue(label) {
|
function useLabeledValue(label) {
|
||||||
|
|
|
@ -39,7 +39,7 @@ export const disableModulePatternComponents = false;
|
||||||
export const enableSuspenseAvoidThisFallback = false;
|
export const enableSuspenseAvoidThisFallback = false;
|
||||||
export const enableSuspenseAvoidThisFallbackFizz = false;
|
export const enableSuspenseAvoidThisFallbackFizz = false;
|
||||||
export const enableCPUSuspense = false;
|
export const enableCPUSuspense = false;
|
||||||
export const enableUseMemoCacheHook = false;
|
export const enableUseMemoCacheHook = true;
|
||||||
export const enableUseEffectEventHook = false;
|
export const enableUseEffectEventHook = false;
|
||||||
export const enableClientRenderFallbackOnTextMismatch = true;
|
export const enableClientRenderFallbackOnTextMismatch = true;
|
||||||
export const enableComponentStackLocations = true;
|
export const enableComponentStackLocations = true;
|
||||||
|
|
Loading…
Reference in New Issue