diff --git a/src/core/Bridge/Suspense.js b/src/core/Bridge/Suspense.js index 1828fb9..91afeb1 100644 --- a/src/core/Bridge/Suspense.js +++ b/src/core/Bridge/Suspense.js @@ -9,10 +9,20 @@ const Lazy = isSupported ? lazy(() => new Promise(() => null)) : () => null class FallbackListener extends Component { componentDidMount() { - run(this.props, 'onStart') + // Defer onStart to a microtask to break the synchronous render loop + // that occurs with React 18's createRoot. Without this, the cycle + // componentDidMount → setState → re-render → throw promise → Suspense + // fallback → componentDidMount repeats synchronously until React's + // max update depth is exceeded. + Promise.resolve().then(() => { + if (!this._unmounted) { + run(this.props, 'onStart') + } + }) } componentWillUnmount() { + this._unmounted = true run(this.props, 'onEnd') } diff --git a/src/core/Keeper.js b/src/core/Keeper.js index cc7fb6d..fc337cc 100644 --- a/src/core/Keeper.js +++ b/src/core/Keeper.js @@ -1,5 +1,6 @@ import React, { PureComponent, Suspense } from 'react' -import { flushSync } from 'react-dom' +// flushSync removed — it forces synchronous rendering inside createRoot, +// bypassing React 18's automatic batching and causing infinite update loops. import { get, run, nextTick, EventBus } from 'szfe-tools' import ReactFreeze from './Freeze' @@ -103,10 +104,8 @@ export default class Keeper extends PureComponent { // 缓存后,延迟冻结,保证各项后续处理得以进行,如关闭弹窗等 clearTimeout(this.freezeTimeout) this.freezeTimeout = setTimeout(() => { - flushSync(() => { - this.safeSetState({ - freeze: true, - }) + this.safeSetState({ + freeze: true, }) }, 1000) }