@player-ui/react-subscribe 0.11.3--canary.670.23708 → 0.11.3--canary.670.24048

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -143,7 +143,7 @@ function useSubscribedState(subscriber) {
143
143
  }
144
144
  );
145
145
  return () => {
146
- if (subscriber && id) {
146
+ if (subscriber) {
147
147
  subscriber.remove(id);
148
148
  }
149
149
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/react/subscribe/src/index.tsx"],"sourcesContent":["import React from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim\";\n\nexport type SubscribeID = number;\n\ntype ResolveType<T> = (arg?: T) => void;\ntype RejectType = (error?: Error) => void;\ntype StatusType = \"success\" | \"failure\" | \"pending\";\ntype DefferedReturnType<T> = {\n /** a function to resolve the promise */\n resolve: ResolveType<T>;\n\n /** a function to reject the promise */\n reject: RejectType;\n\n /** the status of the promise */\n status: StatusType;\n\n /** a promise to express the above */\n promise: Promise<T>;\n};\n\n/** create a deferred promise */\nfunction deferred<T>(): DefferedReturnType<T> {\n /** the default resolve handler is a noop */\n let resolve: ResolveType<T> = () => undefined;\n\n /** the default reject handler is a noop */\n let reject: RejectType = () => undefined;\n\n let status: StatusType = \"pending\";\n\n const promise = new Promise<T>((res, rej) => {\n resolve = (a?: T) => {\n status = \"success\";\n const resolveFunc = res as ResolveType<T>;\n resolveFunc(a);\n };\n\n reject = (error?: Error) => {\n status = \"failure\";\n rej(error);\n };\n });\n\n return {\n resolve,\n status,\n reject,\n promise,\n };\n}\n\nconst NOT_CALLED = Symbol(\"Subscribe -- Empty Value\");\n/**\n * A pub-sub module that works across the React bridge\n */\nexport class Subscribe<T> {\n private callbacks: Map<SubscribeID, (val: T | undefined) => void> = new Map();\n private deferredResult = deferred<T>();\n private lastValue: T | typeof NOT_CALLED = NOT_CALLED;\n private resetDeferred: DefferedReturnType<void> | null = null;\n constructor() {\n this.publish = this.publish.bind(this);\n this.add = this.add.bind(this);\n this.remove = this.remove.bind(this);\n }\n\n /**\n * Trigger the subscriptions using the provided value\n * if there is a reset in progress, wait for it before publishing a new value.\n */\n async publish(val: T): Promise<void> {\n await this.resetDeferred?.promise;\n this.lastValue = val;\n this.deferredResult.resolve(val);\n this.callbacks.forEach((c) => c(val));\n }\n\n /**\n * Subscribe to updates\n */\n add(\n callback: (arg: T | undefined) => void,\n options?: {\n /** Use the last updated value for this subscription to immediately trigger the onSet callback */\n initializeWithPreviousValue?: boolean;\n },\n ): SubscribeID {\n const id = this.callbacks.size;\n this.callbacks.set(id, callback);\n\n if (\n this.lastValue !== NOT_CALLED &&\n options?.initializeWithPreviousValue === true\n ) {\n callback(this.lastValue);\n }\n\n return id;\n }\n\n /**\n * Remove any updates from the given listener\n */\n remove(id: SubscribeID): void {\n this.callbacks.delete(id);\n }\n\n /**\n * Reset the state of the listener\n * Passing in a promise will defer resetting the view until the promise is resolved\n */\n async reset(promise?: Promise<void>): Promise<void> {\n if (promise) {\n this.resetDeferred = deferred<void>();\n await promise;\n }\n\n if (this.lastValue !== NOT_CALLED) {\n this.deferredResult = deferred();\n }\n\n this.lastValue = NOT_CALLED;\n this.callbacks.forEach((c) => c(undefined));\n\n this.resetDeferred?.resolve();\n this.resetDeferred = null;\n }\n\n /**\n * _Throws_ a promise if the value is still pending\n * Otherwise returns it\n */\n suspend(): T {\n if (this.lastValue === NOT_CALLED) {\n throw this.deferredResult.promise;\n }\n\n return this.lastValue;\n }\n\n /** Get the current value of the subscription */\n get(): T | undefined {\n if (this.lastValue === NOT_CALLED) {\n return undefined;\n }\n\n return this.lastValue;\n }\n}\n\nexport interface SubscribedStateHookOptions {\n /** if the state should trigger suspense when waiting to resolve */\n suspend?: boolean;\n}\n\n/** Subscribe to a state change event in a react component */\nexport function useSubscribedState<T>(subscriber: Subscribe<T>): T | undefined {\n const subscription = React.useMemo(() => {\n function subscribe(callback: (val?: T) => void) {\n const id = subscriber.add(\n (resp) => {\n callback(resp);\n },\n {\n initializeWithPreviousValue: true,\n },\n );\n\n return () => {\n if (subscriber && id) {\n subscriber.remove(id);\n }\n };\n }\n\n return subscribe;\n }, [subscriber]);\n\n function getSnapshot() {\n try {\n return subscriber.get();\n } catch (err) {\n return undefined;\n }\n }\n\n const state = useSyncExternalStore(\n subscription,\n getSnapshot,\n () => undefined,\n );\n\n return state;\n}\n"],"mappings":"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","names":["React"]}
1
+ {"version":3,"sources":["../../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/react/subscribe/src/index.tsx"],"sourcesContent":["import React from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim\";\n\nexport type SubscribeID = number;\n\ntype ResolveType<T> = (arg?: T) => void;\ntype RejectType = (error?: Error) => void;\ntype StatusType = \"success\" | \"failure\" | \"pending\";\ntype DefferedReturnType<T> = {\n /** a function to resolve the promise */\n resolve: ResolveType<T>;\n\n /** a function to reject the promise */\n reject: RejectType;\n\n /** the status of the promise */\n status: StatusType;\n\n /** a promise to express the above */\n promise: Promise<T>;\n};\n\n/** create a deferred promise */\nfunction deferred<T>(): DefferedReturnType<T> {\n /** the default resolve handler is a noop */\n let resolve: ResolveType<T> = () => undefined;\n\n /** the default reject handler is a noop */\n let reject: RejectType = () => undefined;\n\n let status: StatusType = \"pending\";\n\n const promise = new Promise<T>((res, rej) => {\n resolve = (a?: T) => {\n status = \"success\";\n const resolveFunc = res as ResolveType<T>;\n resolveFunc(a);\n };\n\n reject = (error?: Error) => {\n status = \"failure\";\n rej(error);\n };\n });\n\n return {\n resolve,\n status,\n reject,\n promise,\n };\n}\n\nconst NOT_CALLED = Symbol(\"Subscribe -- Empty Value\");\n/**\n * A pub-sub module that works across the React bridge\n */\nexport class Subscribe<T> {\n private callbacks: Map<SubscribeID, (val: T | undefined) => void> = new Map();\n private deferredResult = deferred<T>();\n private lastValue: T | typeof NOT_CALLED = NOT_CALLED;\n private resetDeferred: DefferedReturnType<void> | null = null;\n constructor() {\n this.publish = this.publish.bind(this);\n this.add = this.add.bind(this);\n this.remove = this.remove.bind(this);\n }\n\n /**\n * Trigger the subscriptions using the provided value\n * if there is a reset in progress, wait for it before publishing a new value.\n */\n async publish(val: T): Promise<void> {\n await this.resetDeferred?.promise;\n this.lastValue = val;\n this.deferredResult.resolve(val);\n this.callbacks.forEach((c) => c(val));\n }\n\n /**\n * Subscribe to updates\n */\n add(\n callback: (arg: T | undefined) => void,\n options?: {\n /** Use the last updated value for this subscription to immediately trigger the onSet callback */\n initializeWithPreviousValue?: boolean;\n },\n ): SubscribeID {\n const id = this.callbacks.size;\n this.callbacks.set(id, callback);\n\n if (\n this.lastValue !== NOT_CALLED &&\n options?.initializeWithPreviousValue === true\n ) {\n callback(this.lastValue);\n }\n\n return id;\n }\n\n /**\n * Remove any updates from the given listener\n */\n remove(id: SubscribeID): void {\n this.callbacks.delete(id);\n }\n\n /**\n * Reset the state of the listener\n * Passing in a promise will defer resetting the view until the promise is resolved\n */\n async reset(promise?: Promise<void>): Promise<void> {\n if (promise) {\n this.resetDeferred = deferred<void>();\n await promise;\n }\n\n if (this.lastValue !== NOT_CALLED) {\n this.deferredResult = deferred();\n }\n\n this.lastValue = NOT_CALLED;\n this.callbacks.forEach((c) => c(undefined));\n\n this.resetDeferred?.resolve();\n this.resetDeferred = null;\n }\n\n /**\n * _Throws_ a promise if the value is still pending\n * Otherwise returns it\n */\n suspend(): T {\n if (this.lastValue === NOT_CALLED) {\n throw this.deferredResult.promise;\n }\n\n return this.lastValue;\n }\n\n /** Get the current value of the subscription */\n get(): T | undefined {\n if (this.lastValue === NOT_CALLED) {\n return undefined;\n }\n\n return this.lastValue;\n }\n}\n\nexport interface SubscribedStateHookOptions {\n /** if the state should trigger suspense when waiting to resolve */\n suspend?: boolean;\n}\n\n/** Subscribe to a state change event in a react component */\nexport function useSubscribedState<T>(subscriber: Subscribe<T>): T | undefined {\n const subscription = React.useMemo(() => {\n function subscribe(callback: (val?: T) => void) {\n const id = subscriber.add(\n (resp) => {\n callback(resp);\n },\n {\n initializeWithPreviousValue: true,\n },\n );\n\n return () => {\n if (subscriber) {\n subscriber.remove(id);\n }\n };\n }\n\n return subscribe;\n }, [subscriber]);\n\n function getSnapshot() {\n try {\n return subscriber.get();\n } catch (err) {\n return undefined;\n }\n }\n\n const state = useSyncExternalStore(\n subscription,\n getSnapshot,\n () => undefined,\n );\n\n return state;\n}\n"],"mappings":"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","names":["React"]}
@@ -108,7 +108,7 @@ function useSubscribedState(subscriber) {
108
108
  }
109
109
  );
110
110
  return () => {
111
- if (subscriber && id) {
111
+ if (subscriber) {
112
112
  subscriber.remove(id);
113
113
  }
114
114
  };
package/dist/index.mjs CHANGED
@@ -108,7 +108,7 @@ function useSubscribedState(subscriber) {
108
108
  }
109
109
  );
110
110
  return () => {
111
- if (subscriber && id) {
111
+ if (subscriber) {
112
112
  subscriber.remove(id);
113
113
  }
114
114
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/react/subscribe/src/index.tsx"],"sourcesContent":["import React from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim\";\n\nexport type SubscribeID = number;\n\ntype ResolveType<T> = (arg?: T) => void;\ntype RejectType = (error?: Error) => void;\ntype StatusType = \"success\" | \"failure\" | \"pending\";\ntype DefferedReturnType<T> = {\n /** a function to resolve the promise */\n resolve: ResolveType<T>;\n\n /** a function to reject the promise */\n reject: RejectType;\n\n /** the status of the promise */\n status: StatusType;\n\n /** a promise to express the above */\n promise: Promise<T>;\n};\n\n/** create a deferred promise */\nfunction deferred<T>(): DefferedReturnType<T> {\n /** the default resolve handler is a noop */\n let resolve: ResolveType<T> = () => undefined;\n\n /** the default reject handler is a noop */\n let reject: RejectType = () => undefined;\n\n let status: StatusType = \"pending\";\n\n const promise = new Promise<T>((res, rej) => {\n resolve = (a?: T) => {\n status = \"success\";\n const resolveFunc = res as ResolveType<T>;\n resolveFunc(a);\n };\n\n reject = (error?: Error) => {\n status = \"failure\";\n rej(error);\n };\n });\n\n return {\n resolve,\n status,\n reject,\n promise,\n };\n}\n\nconst NOT_CALLED = Symbol(\"Subscribe -- Empty Value\");\n/**\n * A pub-sub module that works across the React bridge\n */\nexport class Subscribe<T> {\n private callbacks: Map<SubscribeID, (val: T | undefined) => void> = new Map();\n private deferredResult = deferred<T>();\n private lastValue: T | typeof NOT_CALLED = NOT_CALLED;\n private resetDeferred: DefferedReturnType<void> | null = null;\n constructor() {\n this.publish = this.publish.bind(this);\n this.add = this.add.bind(this);\n this.remove = this.remove.bind(this);\n }\n\n /**\n * Trigger the subscriptions using the provided value\n * if there is a reset in progress, wait for it before publishing a new value.\n */\n async publish(val: T): Promise<void> {\n await this.resetDeferred?.promise;\n this.lastValue = val;\n this.deferredResult.resolve(val);\n this.callbacks.forEach((c) => c(val));\n }\n\n /**\n * Subscribe to updates\n */\n add(\n callback: (arg: T | undefined) => void,\n options?: {\n /** Use the last updated value for this subscription to immediately trigger the onSet callback */\n initializeWithPreviousValue?: boolean;\n },\n ): SubscribeID {\n const id = this.callbacks.size;\n this.callbacks.set(id, callback);\n\n if (\n this.lastValue !== NOT_CALLED &&\n options?.initializeWithPreviousValue === true\n ) {\n callback(this.lastValue);\n }\n\n return id;\n }\n\n /**\n * Remove any updates from the given listener\n */\n remove(id: SubscribeID): void {\n this.callbacks.delete(id);\n }\n\n /**\n * Reset the state of the listener\n * Passing in a promise will defer resetting the view until the promise is resolved\n */\n async reset(promise?: Promise<void>): Promise<void> {\n if (promise) {\n this.resetDeferred = deferred<void>();\n await promise;\n }\n\n if (this.lastValue !== NOT_CALLED) {\n this.deferredResult = deferred();\n }\n\n this.lastValue = NOT_CALLED;\n this.callbacks.forEach((c) => c(undefined));\n\n this.resetDeferred?.resolve();\n this.resetDeferred = null;\n }\n\n /**\n * _Throws_ a promise if the value is still pending\n * Otherwise returns it\n */\n suspend(): T {\n if (this.lastValue === NOT_CALLED) {\n throw this.deferredResult.promise;\n }\n\n return this.lastValue;\n }\n\n /** Get the current value of the subscription */\n get(): T | undefined {\n if (this.lastValue === NOT_CALLED) {\n return undefined;\n }\n\n return this.lastValue;\n }\n}\n\nexport interface SubscribedStateHookOptions {\n /** if the state should trigger suspense when waiting to resolve */\n suspend?: boolean;\n}\n\n/** Subscribe to a state change event in a react component */\nexport function useSubscribedState<T>(subscriber: Subscribe<T>): T | undefined {\n const subscription = React.useMemo(() => {\n function subscribe(callback: (val?: T) => void) {\n const id = subscriber.add(\n (resp) => {\n callback(resp);\n },\n {\n initializeWithPreviousValue: true,\n },\n );\n\n return () => {\n if (subscriber && id) {\n subscriber.remove(id);\n }\n };\n }\n\n return subscribe;\n }, [subscriber]);\n\n function getSnapshot() {\n try {\n return subscriber.get();\n } catch (err) {\n return undefined;\n }\n }\n\n const state = useSyncExternalStore(\n subscription,\n getSnapshot,\n () => undefined,\n );\n\n return state;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../../../../../../../../execroot/_main/bazel-out/k8-fastbuild/bin/react/subscribe/src/index.tsx"],"sourcesContent":["import React from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim\";\n\nexport type SubscribeID = number;\n\ntype ResolveType<T> = (arg?: T) => void;\ntype RejectType = (error?: Error) => void;\ntype StatusType = \"success\" | \"failure\" | \"pending\";\ntype DefferedReturnType<T> = {\n /** a function to resolve the promise */\n resolve: ResolveType<T>;\n\n /** a function to reject the promise */\n reject: RejectType;\n\n /** the status of the promise */\n status: StatusType;\n\n /** a promise to express the above */\n promise: Promise<T>;\n};\n\n/** create a deferred promise */\nfunction deferred<T>(): DefferedReturnType<T> {\n /** the default resolve handler is a noop */\n let resolve: ResolveType<T> = () => undefined;\n\n /** the default reject handler is a noop */\n let reject: RejectType = () => undefined;\n\n let status: StatusType = \"pending\";\n\n const promise = new Promise<T>((res, rej) => {\n resolve = (a?: T) => {\n status = \"success\";\n const resolveFunc = res as ResolveType<T>;\n resolveFunc(a);\n };\n\n reject = (error?: Error) => {\n status = \"failure\";\n rej(error);\n };\n });\n\n return {\n resolve,\n status,\n reject,\n promise,\n };\n}\n\nconst NOT_CALLED = Symbol(\"Subscribe -- Empty Value\");\n/**\n * A pub-sub module that works across the React bridge\n */\nexport class Subscribe<T> {\n private callbacks: Map<SubscribeID, (val: T | undefined) => void> = new Map();\n private deferredResult = deferred<T>();\n private lastValue: T | typeof NOT_CALLED = NOT_CALLED;\n private resetDeferred: DefferedReturnType<void> | null = null;\n constructor() {\n this.publish = this.publish.bind(this);\n this.add = this.add.bind(this);\n this.remove = this.remove.bind(this);\n }\n\n /**\n * Trigger the subscriptions using the provided value\n * if there is a reset in progress, wait for it before publishing a new value.\n */\n async publish(val: T): Promise<void> {\n await this.resetDeferred?.promise;\n this.lastValue = val;\n this.deferredResult.resolve(val);\n this.callbacks.forEach((c) => c(val));\n }\n\n /**\n * Subscribe to updates\n */\n add(\n callback: (arg: T | undefined) => void,\n options?: {\n /** Use the last updated value for this subscription to immediately trigger the onSet callback */\n initializeWithPreviousValue?: boolean;\n },\n ): SubscribeID {\n const id = this.callbacks.size;\n this.callbacks.set(id, callback);\n\n if (\n this.lastValue !== NOT_CALLED &&\n options?.initializeWithPreviousValue === true\n ) {\n callback(this.lastValue);\n }\n\n return id;\n }\n\n /**\n * Remove any updates from the given listener\n */\n remove(id: SubscribeID): void {\n this.callbacks.delete(id);\n }\n\n /**\n * Reset the state of the listener\n * Passing in a promise will defer resetting the view until the promise is resolved\n */\n async reset(promise?: Promise<void>): Promise<void> {\n if (promise) {\n this.resetDeferred = deferred<void>();\n await promise;\n }\n\n if (this.lastValue !== NOT_CALLED) {\n this.deferredResult = deferred();\n }\n\n this.lastValue = NOT_CALLED;\n this.callbacks.forEach((c) => c(undefined));\n\n this.resetDeferred?.resolve();\n this.resetDeferred = null;\n }\n\n /**\n * _Throws_ a promise if the value is still pending\n * Otherwise returns it\n */\n suspend(): T {\n if (this.lastValue === NOT_CALLED) {\n throw this.deferredResult.promise;\n }\n\n return this.lastValue;\n }\n\n /** Get the current value of the subscription */\n get(): T | undefined {\n if (this.lastValue === NOT_CALLED) {\n return undefined;\n }\n\n return this.lastValue;\n }\n}\n\nexport interface SubscribedStateHookOptions {\n /** if the state should trigger suspense when waiting to resolve */\n suspend?: boolean;\n}\n\n/** Subscribe to a state change event in a react component */\nexport function useSubscribedState<T>(subscriber: Subscribe<T>): T | undefined {\n const subscription = React.useMemo(() => {\n function subscribe(callback: (val?: T) => void) {\n const id = subscriber.add(\n (resp) => {\n callback(resp);\n },\n {\n initializeWithPreviousValue: true,\n },\n );\n\n return () => {\n if (subscriber) {\n subscriber.remove(id);\n }\n };\n }\n\n return subscribe;\n }, [subscriber]);\n\n function getSnapshot() {\n try {\n return subscriber.get();\n } catch (err) {\n return undefined;\n }\n }\n\n const state = useSyncExternalStore(\n subscription,\n getSnapshot,\n () => undefined,\n );\n\n return state;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "types"
7
7
  ],
8
8
  "name": "@player-ui/react-subscribe",
9
- "version": "0.11.3--canary.670.23708",
9
+ "version": "0.11.3--canary.670.24048",
10
10
  "main": "dist/cjs/index.cjs",
11
11
  "module": "dist/index.legacy-esm.js",
12
12
  "types": "types/index.d.ts",
@@ -0,0 +1,83 @@
1
+ import { test, vitest, expect, describe, vi } from "vitest";
2
+ import { renderHook } from "@testing-library/react";
3
+ import { Subscribe, useSubscribedState } from ".";
4
+
5
+ test("Passes events to subscriptions", async () => {
6
+ const stateSub = new Subscribe<{
7
+ value: boolean;
8
+ }>();
9
+ const { add, publish } = stateSub;
10
+ const f = vitest.fn();
11
+ add(f);
12
+ publish({ value: true });
13
+
14
+ await vitest.waitFor(() => expect(f).toBeCalledTimes(1));
15
+ expect(f.mock.calls[0][0].value).toBe(true);
16
+ });
17
+
18
+ test("Removes subscriptions", async () => {
19
+ const stateSub = new Subscribe<{
20
+ value: boolean;
21
+ }>();
22
+ const { add, remove, publish } = stateSub;
23
+ const f = vitest.fn();
24
+ const id = add(f);
25
+ remove(id);
26
+ publish({ value: true });
27
+
28
+ await vitest.waitFor(() => expect(f).not.toHaveBeenCalled());
29
+ });
30
+
31
+ test("Calls multiple", async () => {
32
+ const stateSub = new Subscribe<{
33
+ value: boolean;
34
+ }>();
35
+ const { add, publish } = stateSub;
36
+ const f = vitest.fn();
37
+ const g = vitest.fn();
38
+ add(f);
39
+ add(g);
40
+ publish({ value: true });
41
+
42
+ await vitest.waitFor(() => expect(f).toBeCalledTimes(1));
43
+ expect(g).toBeCalledTimes(1);
44
+ });
45
+
46
+ describe("useSubscribedState", () => {
47
+ test("updates value based on Subscriber changes", async () => {
48
+ const stateSub = new Subscribe<boolean>();
49
+ const addSpy = vi.spyOn(stateSub, "add");
50
+ const removeSpy = vi.spyOn(stateSub, "remove");
51
+
52
+ const { result, rerender, unmount } = renderHook(() =>
53
+ useSubscribedState(stateSub),
54
+ );
55
+ expect(result.current).toBeUndefined();
56
+ expect(addSpy).toHaveBeenCalledTimes(1);
57
+ expect(removeSpy).toHaveBeenCalledTimes(0);
58
+
59
+ await stateSub.publish(true);
60
+ expect(result.current).toBe(true);
61
+ expect(addSpy).toHaveBeenCalledTimes(1);
62
+ expect(removeSpy).toHaveBeenCalledTimes(0);
63
+
64
+ await stateSub.publish(false);
65
+ expect(result.current).toBe(false);
66
+ expect(addSpy).toHaveBeenCalledTimes(1);
67
+ expect(removeSpy).toHaveBeenCalledTimes(0);
68
+
69
+ rerender();
70
+ expect(result.current).toBe(false);
71
+ expect(addSpy).toHaveBeenCalledTimes(1);
72
+ expect(removeSpy).toHaveBeenCalledTimes(0);
73
+
74
+ await stateSub.reset();
75
+ expect(result.current).toBeUndefined();
76
+ expect(addSpy).toHaveBeenCalledTimes(1);
77
+ expect(removeSpy).toHaveBeenCalledTimes(0);
78
+
79
+ unmount();
80
+ expect(addSpy).toHaveBeenCalledTimes(1);
81
+ expect(removeSpy).toHaveBeenCalledTimes(1);
82
+ });
83
+ });
package/src/index.tsx CHANGED
@@ -169,7 +169,7 @@ export function useSubscribedState<T>(subscriber: Subscribe<T>): T | undefined {
169
169
  );
170
170
 
171
171
  return () => {
172
- if (subscriber && id) {
172
+ if (subscriber) {
173
173
  subscriber.remove(id);
174
174
  }
175
175
  };
package/src/index.test.ts DELETED
@@ -1,43 +0,0 @@
1
- import { test, vitest, expect } from "vitest";
2
- import { Subscribe } from ".";
3
-
4
- test("Passes events to subscriptions", async () => {
5
- const stateSub = new Subscribe<{
6
- value: boolean;
7
- }>();
8
- const { add, publish } = stateSub;
9
- const f = vitest.fn();
10
- add(f);
11
- publish({ value: true });
12
-
13
- await vitest.waitFor(() => expect(f).toBeCalledTimes(1));
14
- expect(f.mock.calls[0][0].value).toBe(true);
15
- });
16
-
17
- test("Removes subscriptions", async () => {
18
- const stateSub = new Subscribe<{
19
- value: boolean;
20
- }>();
21
- const { add, remove, publish } = stateSub;
22
- const f = vitest.fn();
23
- const id = add(f);
24
- remove(id);
25
- publish({ value: true });
26
-
27
- await vitest.waitFor(() => expect(f).not.toHaveBeenCalled());
28
- });
29
-
30
- test("Calls multiple", async () => {
31
- const stateSub = new Subscribe<{
32
- value: boolean;
33
- }>();
34
- const { add, publish } = stateSub;
35
- const f = vitest.fn();
36
- const g = vitest.fn();
37
- add(f);
38
- add(g);
39
- publish({ value: true });
40
-
41
- await vitest.waitFor(() => expect(f).toBeCalledTimes(1));
42
- expect(g).toBeCalledTimes(1);
43
- });