Skip to content

Commit 67cace9

Browse files
committed
feat: pass context to subscriptions
1 parent fb8f502 commit 67cace9

3 files changed

Lines changed: 49 additions & 13 deletions

File tree

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,12 @@ const state = createFactory({ count: 0, bool: true }).create(/* context */ undef
129129

130130
It's possible to define [subscriptions](https://github.com/pmndrs/valtio/blob/main/readme.md#subscribe-from-anywhere) on the whole state using the factory pattern.
131131

132+
The subscription callback function receives the state object as a first argument, then the
133+
factory's context, and the rest of valtio's arguments for the subscribe callback last.
134+
132135
```ts
133136
const state = createFactory({ count: 0 })
134-
.subscribe((state) => {
137+
.subscribe((state, context) => {
135138
console.log('current state:', state);
136139
})
137140
.create();
@@ -142,7 +145,7 @@ const state = createFactory({ count: 0 })
142145
To conveniently subscribe to a snapshot of the state, use `subscribeSnapshot`.
143146

144147
```ts
145-
createFactory({ count: 0 }).subscribeSnapshot((snap) => {
148+
createFactory({ count: 0 }).subscribeSnapshot((snap, context) => {
146149
// `snap` is an immutable object
147150
});
148151
```
@@ -315,4 +318,4 @@ function Counter() {
315318

316319
### Example
317320

318-
You can find an example with React and valtio-factory in this repository at [example/](example/README.md) or on [Codesandbox](https://codesandbox.io/s/valtio-factory-example-j7v2s).
321+
You can find an example with React and valtio-factory in this repository at [example/](example/) or on [Codesandbox](https://codesandbox.io/s/valtio-factory-example-j7v2s).

lib/store-factory.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,30 @@ describe('store-factory', () => {
124124
expect(count).toBe(1);
125125
});
126126

127+
test('subscribe and subscribeSnapshot should receive context', () => {
128+
type State = { count: number };
129+
130+
const context = { fn: jest.fn() };
131+
type Context = typeof context;
132+
133+
const state = createFactory<State, Context>({ count: 0 })
134+
.actions({
135+
increment() {
136+
this.count += 1;
137+
},
138+
})
139+
.subscribe((_, context) => {
140+
context.fn();
141+
}, /* notifyInSync */ true)
142+
.subscribeSnapshot((_, context) => {
143+
context.fn();
144+
}, /* notifyInSync */ true)
145+
.create(context);
146+
147+
state.increment();
148+
expect(context.fn).toHaveBeenCalledTimes(2);
149+
});
150+
127151
test('onCreate', () => {
128152
let count = 0;
129153

lib/store-factory.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,18 @@ import { ParametersAfterSecond, Snapshot, UnsubscribeFn, WithContext } from './t
77

88
type AdditionalSubscribeArgs = ParametersAfterSecond<typeof subscribe>;
99

10-
type SubscriptionFn<S extends {}> = (
11-
state: S,
10+
/**
11+
* Subscription callback function that will receive the state (or snapshot) as a
12+
* first argument, the context as a second argument, and the rest of the arguments
13+
* of valtio's {@link subscribe} function.
14+
*/
15+
type SubscriptionFn<State extends {}, Context> = (
16+
state: State,
17+
context: Context,
1218
...args: Parameters<Parameters<typeof subscribe>[1]>
1319
) => void;
1420

15-
type Subscription<S extends {}> = [SubscriptionFn<S>, ...AdditionalSubscribeArgs];
21+
type Subscription<S extends {}, Context> = [SubscriptionFn<S, Context>, ...AdditionalSubscribeArgs];
1622

1723
/**
1824
* Create a new store factory.
@@ -93,7 +99,7 @@ export interface Factory<S extends {}, C extends {}, A extends Actions<S & U, C>
9399

94100
/**
95101
* Subscribe to the full state object.
96-
* @param subscription Function that will receive the current state.
102+
* @param subscription Function ({@link SubscriptionFn}) that will receive the current state.
97103
* @param args Additinal arguments of the {@link subscribe} function.
98104
* @returns The store factory.
99105
* @example
@@ -105,7 +111,10 @@ export interface Factory<S extends {}, C extends {}, A extends Actions<S & U, C>
105111
* ```
106112
* @see https://github.com/pmndrs/valtio#subscribe-from-anywhere
107113
*/
108-
subscribe(subscription: SubscriptionFn<S>, ...args: AdditionalSubscribeArgs): Factory<S, C, A, U>;
114+
subscribe(
115+
subscription: SubscriptionFn<S, C>,
116+
...args: AdditionalSubscribeArgs
117+
): Factory<S, C, A, U>;
109118

110119
/**
111120
* Subscribe to a snaphshot of the full state object.
@@ -124,7 +133,7 @@ export interface Factory<S extends {}, C extends {}, A extends Actions<S & U, C>
124133
* @see https://github.com/pmndrs/valtio#use-it-vanilla
125134
*/
126135
subscribeSnapshot(
127-
subscription: SubscriptionFn<Snapshot<S>>,
136+
subscription: SubscriptionFn<Snapshot<S>, C>,
128137
...args: AdditionalSubscribeArgs
129138
): Factory<S, C, A, U>;
130139

@@ -188,7 +197,7 @@ function factory<S extends {}, C extends {}, A extends Actions<S & U, C>, U exte
188197
baseState: S;
189198
baseActions: A;
190199
baseDerivedProps: DerivedProps<S, U>;
191-
baseSubscriptions: Subscription<S>[];
200+
baseSubscriptions: Subscription<S, C>[];
192201
unsubscriptions: Array<() => void>;
193202
onCreate: OnCreateFn<S, C, A, U>;
194203
}): Factory<S, C, A, U> {
@@ -217,7 +226,7 @@ function factory<S extends {}, C extends {}, A extends Actions<S & U, C>, U exte
217226
});
218227
},
219228

220-
subscribe: (subscription: SubscriptionFn<S>, ...args: AdditionalSubscribeArgs) => {
229+
subscribe: (subscription: SubscriptionFn<S, C>, ...args: AdditionalSubscribeArgs) => {
221230
return factory<S, C, A, U>({
222231
baseState,
223232
baseActions,
@@ -229,7 +238,7 @@ function factory<S extends {}, C extends {}, A extends Actions<S & U, C>, U exte
229238
},
230239

231240
subscribeSnapshot: (
232-
subscription: SubscriptionFn<Snapshot<S>>,
241+
subscription: SubscriptionFn<Snapshot<S>, C>,
233242
...args: AdditionalSubscribeArgs
234243
) => {
235244
return factory<S, C, A, U>({
@@ -303,7 +312,7 @@ function factory<S extends {}, C extends {}, A extends Actions<S & U, C>, U exte
303312
const unsubscription = subscribe(
304313
derivedProxy,
305314
(ops) => {
306-
subscribtion(derivedProxy, ops);
315+
subscribtion(derivedProxy, context, ops);
307316
},
308317
...args,
309318
);

0 commit comments

Comments
 (0)