mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
Devtools: Display actual pending state when inspecting useTransition (#28499)
This commit is contained in:
committed by
GitHub
parent
c11b196ae3
commit
0066e0b68d
@@ -427,16 +427,19 @@ function useTransition(): [
|
||||
// useTransition() composes multiple hooks internally.
|
||||
// Advance the current hook index the same number of times
|
||||
// so that subsequent hooks have the right memoized state.
|
||||
nextHook(); // State
|
||||
const stateHook = nextHook();
|
||||
nextHook(); // Callback
|
||||
|
||||
const isPending = stateHook !== null ? stateHook.memoizedState : false;
|
||||
|
||||
hookLog.push({
|
||||
displayName: null,
|
||||
primitive: 'Transition',
|
||||
stackError: new Error(),
|
||||
value: undefined,
|
||||
value: isPending,
|
||||
debugInfo: null,
|
||||
});
|
||||
return [false, callback => {}];
|
||||
return [isPending, () => {}];
|
||||
}
|
||||
|
||||
function useDeferredValue<T>(value: T, initialValue?: T): T {
|
||||
|
||||
@@ -952,7 +952,7 @@ describe('ReactHooksInspectionIntegration', () => {
|
||||
"isStateEditable": false,
|
||||
"name": "Transition",
|
||||
"subHooks": [],
|
||||
"value": undefined,
|
||||
"value": false,
|
||||
},
|
||||
{
|
||||
"debugInfo": null,
|
||||
@@ -986,6 +986,168 @@ describe('ReactHooksInspectionIntegration', () => {
|
||||
`);
|
||||
});
|
||||
|
||||
it('should update isPending returned from useTransition', async () => {
|
||||
const IndefiniteSuspender = React.lazy(() => new Promise(() => {}));
|
||||
let startTransition;
|
||||
function Foo(props) {
|
||||
const [show, setShow] = React.useState(false);
|
||||
const [isPending, _startTransition] = React.useTransition();
|
||||
React.useMemo(() => 'hello', []);
|
||||
React.useMemo(() => 'not used', []);
|
||||
|
||||
// Otherwise we capture the version from the react-debug-tools dispatcher.
|
||||
if (startTransition === undefined) {
|
||||
startTransition = () => {
|
||||
_startTransition(() => {
|
||||
setShow(true);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Suspense fallback="Loading">
|
||||
{isPending ? 'Pending' : null}
|
||||
{show ? <IndefiniteSuspender /> : null}
|
||||
</React.Suspense>
|
||||
);
|
||||
}
|
||||
const renderer = await act(() => {
|
||||
return ReactTestRenderer.create(<Foo />, {isConcurrent: true});
|
||||
});
|
||||
expect(renderer).toMatchRenderedOutput(null);
|
||||
let childFiber = renderer.root.findByType(Foo)._currentFiber();
|
||||
let tree = ReactDebugTools.inspectHooksOfFiber(childFiber);
|
||||
expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"debugInfo": null,
|
||||
"hookSource": {
|
||||
"columnNumber": 0,
|
||||
"fileName": "**",
|
||||
"functionName": "Foo",
|
||||
"lineNumber": 0,
|
||||
},
|
||||
"id": 0,
|
||||
"isStateEditable": true,
|
||||
"name": "State",
|
||||
"subHooks": [],
|
||||
"value": false,
|
||||
},
|
||||
{
|
||||
"debugInfo": null,
|
||||
"hookSource": {
|
||||
"columnNumber": 0,
|
||||
"fileName": "**",
|
||||
"functionName": "Foo",
|
||||
"lineNumber": 0,
|
||||
},
|
||||
"id": 1,
|
||||
"isStateEditable": false,
|
||||
"name": "Transition",
|
||||
"subHooks": [],
|
||||
"value": false,
|
||||
},
|
||||
{
|
||||
"debugInfo": null,
|
||||
"hookSource": {
|
||||
"columnNumber": 0,
|
||||
"fileName": "**",
|
||||
"functionName": "Foo",
|
||||
"lineNumber": 0,
|
||||
},
|
||||
"id": 2,
|
||||
"isStateEditable": false,
|
||||
"name": "Memo",
|
||||
"subHooks": [],
|
||||
"value": "hello",
|
||||
},
|
||||
{
|
||||
"debugInfo": null,
|
||||
"hookSource": {
|
||||
"columnNumber": 0,
|
||||
"fileName": "**",
|
||||
"functionName": "Foo",
|
||||
"lineNumber": 0,
|
||||
},
|
||||
"id": 3,
|
||||
"isStateEditable": false,
|
||||
"name": "Memo",
|
||||
"subHooks": [],
|
||||
"value": "not used",
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
||||
await act(() => {
|
||||
startTransition();
|
||||
});
|
||||
|
||||
expect(renderer).toMatchRenderedOutput('Pending');
|
||||
|
||||
childFiber = renderer.root.findByType(Foo)._currentFiber();
|
||||
tree = ReactDebugTools.inspectHooksOfFiber(childFiber);
|
||||
expect(normalizeSourceLoc(tree)).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"debugInfo": null,
|
||||
"hookSource": {
|
||||
"columnNumber": 0,
|
||||
"fileName": "**",
|
||||
"functionName": "Foo",
|
||||
"lineNumber": 0,
|
||||
},
|
||||
"id": 0,
|
||||
"isStateEditable": true,
|
||||
"name": "State",
|
||||
"subHooks": [],
|
||||
"value": false,
|
||||
},
|
||||
{
|
||||
"debugInfo": null,
|
||||
"hookSource": {
|
||||
"columnNumber": 0,
|
||||
"fileName": "**",
|
||||
"functionName": "Foo",
|
||||
"lineNumber": 0,
|
||||
},
|
||||
"id": 1,
|
||||
"isStateEditable": false,
|
||||
"name": "Transition",
|
||||
"subHooks": [],
|
||||
"value": true,
|
||||
},
|
||||
{
|
||||
"debugInfo": null,
|
||||
"hookSource": {
|
||||
"columnNumber": 0,
|
||||
"fileName": "**",
|
||||
"functionName": "Foo",
|
||||
"lineNumber": 0,
|
||||
},
|
||||
"id": 2,
|
||||
"isStateEditable": false,
|
||||
"name": "Memo",
|
||||
"subHooks": [],
|
||||
"value": "hello",
|
||||
},
|
||||
{
|
||||
"debugInfo": null,
|
||||
"hookSource": {
|
||||
"columnNumber": 0,
|
||||
"fileName": "**",
|
||||
"functionName": "Foo",
|
||||
"lineNumber": 0,
|
||||
},
|
||||
"id": 3,
|
||||
"isStateEditable": false,
|
||||
"name": "Memo",
|
||||
"subHooks": [],
|
||||
"value": "not used",
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('should support useDeferredValue hook', () => {
|
||||
function Foo(props) {
|
||||
React.useDeferredValue('abc');
|
||||
|
||||
@@ -120,6 +120,34 @@ function wrapWithHoc(Component: (props: any, ref: React$Ref<any>) => any) {
|
||||
}
|
||||
const HocWithHooks = wrapWithHoc(FunctionWithHooks);
|
||||
|
||||
const Suspendender = React.lazy(() => {
|
||||
return new Promise<any>(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
default: () => 'Finished!',
|
||||
});
|
||||
}, 3000);
|
||||
});
|
||||
});
|
||||
function Transition() {
|
||||
const [show, setShow] = React.useState(false);
|
||||
const [isPending, startTransition] = React.useTransition();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<React.Suspense fallback="Loading">
|
||||
{isPending ? 'Pending' : null}
|
||||
{show ? <Suspendender /> : null}
|
||||
</React.Suspense>
|
||||
{!show && (
|
||||
<button onClick={() => startTransition(() => setShow(true))}>
|
||||
Transition
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function incrementWithDelay(previousState: number, formData: FormData) {
|
||||
const incrementDelay = +formData.get('incrementDelay');
|
||||
const shouldReject = formData.get('shouldReject');
|
||||
@@ -183,6 +211,7 @@ export default function CustomHooks(): React.Node {
|
||||
<MemoWithHooks />
|
||||
<ForwardRefWithHooks />
|
||||
<HocWithHooks />
|
||||
<Transition />
|
||||
<ErrorBoundary>
|
||||
<Forms />
|
||||
</ErrorBoundary>
|
||||
|
||||
Reference in New Issue
Block a user