Skip to content

Commit

Permalink
feat(rippling): store.sub support AbortSignal
Browse files Browse the repository at this point in the history
  • Loading branch information
e7h4n committed Dec 9, 2024
1 parent 6fa5c7a commit fa29c0f
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/clean-cooks-swim.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'rippling': minor
---

feat: store.sub support AbortSignal
14 changes: 12 additions & 2 deletions packages/rippling/src/core/store.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ReadableAtom, Effect, Getter, Value, Updater, Setter } from '../../types/core/atom';
import type { Store } from '../../types/core/store';
import type { Store, SubscribeOptions } from '../../types/core/store';
import { AtomManager, ListenerManager } from './atom-manager';

export class StoreImpl implements Store {
Expand Down Expand Up @@ -75,7 +75,11 @@ export class StoreImpl implements Store {
};
}

sub(atoms: ReadableAtom<unknown>[] | ReadableAtom<unknown>, cbEffect: Effect<unknown, unknown[]>): () => void {
sub(
atoms: ReadableAtom<unknown>[] | ReadableAtom<unknown>,
cbEffect: Effect<unknown, unknown[]>,
options?: SubscribeOptions,
): () => void {
if (Array.isArray(atoms) && atoms.length === 0) {
return () => void 0;
}
Expand All @@ -91,6 +95,12 @@ export class StoreImpl implements Store {
unsubscribes.add(this._subSingleAtom(atom, cbEffect));
});

options?.signal?.addEventListener('abort', () => {
for (const unsubscribe of unsubscribes) {
unsubscribe();
}
});

return () => {
for (const unsubscribe of unsubscribes) {
unsubscribe();
Expand Down
6 changes: 5 additions & 1 deletion packages/rippling/src/react/useGet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ export function useGet<T>(atom: Value<T> | Computed<T>) {
const store = useStore();
return useSyncExternalStore(
(fn) => {
return store.sub(atom, $effect(fn));
const ctrl = new AbortController();
store.sub(atom, $effect(fn), { signal: ctrl.signal });
return () => {
ctrl.abort();
};
},
() => {
return store.get(atom);
Expand Down
5 changes: 5 additions & 0 deletions packages/rippling/types/core/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ export interface Store {
sub: Subscribe;
}

export interface SubscribeOptions {
signal?: AbortSignal;
}

export type Subscribe = (
atoms: ReadableAtom<unknown>[] | ReadableAtom<unknown>,
callback: Effect<unknown, unknown[]>,
options?: SubscribeOptions,
) => () => void;

0 comments on commit fa29c0f

Please sign in to comment.