()
| 549 | } |
| 550 | |
| 551 | queueUpdate(): void { |
| 552 | if (this.dirtyNodes.size === 0 || this.queuedRender) { |
| 553 | return; |
| 554 | } |
| 555 | |
| 556 | // Only trigger subscriptions once during an update, when the first item changes. |
| 557 | // React's useSyncExternalStore will call getCollection immediately, to check whether the snapshot changed. |
| 558 | // If so, React will queue a render to happen after the current commit to our fake DOM finishes. |
| 559 | // We track whether getCollection is called in a subscription, and once it is called during render, |
| 560 | // we reset queuedRender back to false. |
| 561 | this.queuedRender = true; |
| 562 | this.inSubscription = true; |
| 563 | |
| 564 | // Clone the collection to ensure that React queues a render. It will call getCollection again |
| 565 | // during render, at which point all the updates will be complete and we can return |
| 566 | // the new collection. |
| 567 | if (!this.isSSR) { |
| 568 | this.collection = this.collection.clone(); |
| 569 | } |
| 570 | |
| 571 | for (let fn of this.subscriptions) { |
| 572 | fn(); |
| 573 | } |
| 574 | |
| 575 | this.inSubscription = false; |
| 576 | } |
| 577 | |
| 578 | subscribe(fn: () => void) { |
| 579 | this.subscriptions.add(fn); |
no test coverage detected