Skip to content

Commit a986e17

Browse files
authored
Fix crash when suspending in Components using useActionQueue (#85459)
1 parent 4067214 commit a986e17

File tree

1 file changed

+26
-8
lines changed

1 file changed

+26
-8
lines changed

packages/next/src/client/components/use-action-queue.ts

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ export function dispatchAppRouterAction(action: ReducerActions) {
2222
dispatch(action)
2323
}
2424

25+
const __DEV__ = process.env.NODE_ENV !== 'production'
26+
const promisesWithDebugInfo: WeakMap<
27+
Promise<AppRouterState>,
28+
Promise<AppRouterState> & { _debugInfo?: Array<unknown> }
29+
> = __DEV__ ? new WeakMap() : (null as any)
30+
2531
export function useActionQueue(
2632
actionQueue: AppRouterActionQueue
2733
): AppRouterState {
@@ -56,15 +62,27 @@ export function useActionQueue(
5662
// passed to React (via `use`) so that the latency is accurately represented
5763
// in the React DevTools.
5864
const stateWithDebugInfo = useMemo(() => {
65+
if (!__DEV__) {
66+
return state
67+
}
68+
5969
if (isThenable(state)) {
60-
const debugInfo: Array<unknown> = []
61-
const promiseWithDebugInfo = Promise.resolve(state).then((asyncState) => {
62-
if (asyncState.debugInfo !== null) {
63-
debugInfo.push(...asyncState.debugInfo)
64-
}
65-
return asyncState
66-
}) as Promise<AppRouterState> & { _debugInfo?: Array<unknown> }
67-
promiseWithDebugInfo._debugInfo = debugInfo
70+
// useMemo can't be used to cache a Promise since the memoized value is thrown
71+
// away when we suspend. So we use a WeakMap to cache the Promise with debug info.
72+
let promiseWithDebugInfo = promisesWithDebugInfo.get(state)
73+
if (promiseWithDebugInfo === undefined) {
74+
const debugInfo: Array<unknown> = []
75+
promiseWithDebugInfo = Promise.resolve(state).then((asyncState) => {
76+
if (asyncState.debugInfo !== null) {
77+
debugInfo.push(...asyncState.debugInfo)
78+
}
79+
return asyncState
80+
}) as Promise<AppRouterState> & { _debugInfo?: Array<unknown> }
81+
promiseWithDebugInfo._debugInfo = debugInfo
82+
83+
promisesWithDebugInfo.set(state, promiseWithDebugInfo)
84+
}
85+
6886
return promiseWithDebugInfo
6987
}
7088
return state

0 commit comments

Comments
 (0)