diff --git a/packages/react-reconciler/src/__tests__/ReactUse-test.js b/packages/react-reconciler/src/__tests__/ReactUse-test.js index dede68854c615..a9f8ca4313347 100644 --- a/packages/react-reconciler/src/__tests__/ReactUse-test.js +++ b/packages/react-reconciler/src/__tests__/ReactUse-test.js @@ -16,6 +16,7 @@ let act; let use; let useDebugValue; let useState; +let useTransition; let useMemo; let useEffect; let Suspense; @@ -38,6 +39,7 @@ describe('ReactUse', () => { use = React.use; useDebugValue = React.useDebugValue; useState = React.useState; + useTransition = React.useTransition; useMemo = React.useMemo; useEffect = React.useEffect; Suspense = React.Suspense; @@ -1915,4 +1917,62 @@ describe('ReactUse', () => { assertLog(['Hi', 'World']); expect(root).toMatchRenderedOutput(
Hi World
); }); + + it('does not get stuck in pending state with usable values in state', async () => { + const initial = new Promise(resolve => { + setTimeout(() => { + resolve('initial'); + }, 1000); + }); + let click; + function Reader({promise, setPromise}) { + const value = use(promise); + const [isPending, startLocalTransition] = useTransition(); + click = () => { + startLocalTransition(() => { + setPromise( + new Promise(resolve => { + setTimeout(() => { + resolve('updated'); + }, 1000); + }), + ); + }); + }; + + Scheduler.log(`Value: ${value}, Pending: ${String(isPending)}`); + + return ( + <> + Value: {value}, Pending: {String(isPending)} + + ); + } + function App() { + const [promise, setPromise] = useState(initial); + + return ( + + + + ); + } + + const root = ReactNoop.createRoot(); + await act(() => { + root.render(); + }); + assertLog(['Value: initial, Pending: false']); + expect(root).toMatchRenderedOutput('Value: initial, Pending: false'); + + await act(() => { + click(); + }); + + assertLog([ + 'Value: initial, Pending: true', + 'Value: updated, Pending: true', + ]); + expect(root).toMatchRenderedOutput('Value: updated, Pending: true'); + }); });