Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/nasty-rings-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@preact/signals-react": major
---

Delay subscribing to signals until the component is actually mounted
19 changes: 19 additions & 0 deletions packages/react/runtime/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,24 @@ export interface EffectStore {
getSnapshot(): number;
/** startEffect - begin tracking signals used in this component */
_start(): void;
_subscribers: Array<{ signal: Signal; node: any }>;
_sub: typeof Signal.prototype._subscribe;
/** finishEffect - stop tracking the signals used in this component */
f(): void;
[symDispose](): void;
}

let currentStore: EffectStore | undefined;

const realSubscribe = Signal.prototype._subscribe;
function startComponentEffect(
prevStore: EffectStore | undefined,
nextStore: EffectStore
) {
nextStore._sub = Signal.prototype._subscribe;
Signal.prototype._subscribe = function (this: Signal, node: any) {
nextStore._subscribers.push({ signal: this, node });
};
const endEffect = nextStore.effect._start();
currentStore = nextStore;

Expand All @@ -116,6 +123,7 @@ function finishComponentEffect(
prevStore: EffectStore | undefined,
endEffect: () => void
) {
Signal.prototype._subscribe = this._sub;
endEffect();
currentStore = prevStore;
}
Expand Down Expand Up @@ -157,6 +165,8 @@ function createEffectStore(_usage: EffectStoreUsage): EffectStore {

return {
_usage,
_subscribers: [],
_sub: realSubscribe,
effect: effectInstance,
subscribe(onStoreChange) {
onChangeNotifyReact = onStoreChange;
Expand Down Expand Up @@ -291,6 +301,8 @@ const noop = () => {};

function createEmptyEffectStore(): EffectStore {
return {
_subscribers: [],
_sub: noop as any,
_usage: UNMANAGED,
effect: {
_sources: undefined,
Expand Down Expand Up @@ -354,6 +366,13 @@ export function _useSignalsImplementation(
// note: _usage is a constant here, so conditional is okay
if (_usage === UNMANAGED) useIsomorphicLayoutEffect(cleanupTrailingStore);

useIsomorphicLayoutEffect(() => {
store._subscribers.forEach(({ signal, node }) => {
realSubscribe.call(signal, node);
});
store._subscribers = [];
});

return store;
}

Expand Down
Loading