Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
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/bright-sheep-talk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'zustand-x': minor
---

feat: `store.subscribe` support
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,32 @@ store.set('state', (draft) => {
});
```

### Subscribing State
```ts
// Subscribe to changes
const unsubscribe = store.subscribe('name', (name, previousName) => {
console.log('Name changed from', previousName, 'to', name);
});

// Subscribe to the entire state
const unsubscribe = store.subscribe('state', (state) => {
console.log('State changed:', state);
});

// Subscribe to a selector with arguments
const unsubscribe = store.subscribe('someSelector', 1, 2 (result) => {
console.log('Selector result changed:', result);
});

// Subscribe with an additional selector and options
const unsubscribe = store.subscribe(
'name',
name => name.length,
length => console.log('Name length changed:', length),
{ fireImmediately: true } // Fire the callback immediately when subscribing
);
```

### React Hooks

#### `useStoreValue(store, key, ...args)`
Expand Down
26 changes: 26 additions & 0 deletions packages/zustand-x/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,32 @@ store.set('state', (draft) => {
});
```

### Subscribing State
```ts
// Subscribe to changes
const unsubscribe = store.subscribe('name', (name, previousName) => {
console.log('Name changed from', previousName, 'to', name);
});

// Subscribe to the entire state
const unsubscribe = store.subscribe('state', (state) => {
console.log('State changed:', state);
});

// Subscribe to a selector with arguments
const unsubscribe = store.subscribe('someSelector', 1, 2 (result) => {
console.log('Selector result changed:', result);
});

// Subscribe with an additional selector and options
const unsubscribe = store.subscribe(
'name',
name => name.length,
length => console.log('Name length changed:', length),
{ fireImmediately: true } // Fire the callback immediately when subscribing
);
```

### React Hooks

#### `useStoreValue(store, key, ...args)`
Expand Down
31 changes: 30 additions & 1 deletion packages/zustand-x/src/createStore.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createTrackedSelector } from 'react-tracked';
import { subscribeWithSelector } from 'zustand/middleware';
import { createWithEqualityFn as createStoreZustand } from 'zustand/traditional';

import {
Expand Down Expand Up @@ -92,7 +93,7 @@ export const createStore = <
: () => initializer) as StateCreator<StateType>
) as StateCreator<StateType, [], Mutators>;

const store = createStoreZustand(stateMutators);
const store = createStoreZustand(subscribeWithSelector(stateMutators));

const useTrackedStore = createTrackedSelector(store);

Expand All @@ -108,6 +109,33 @@ export const createStore = <
return store.getState()[key as keyof StateType];
};

const subscribeFn = (
key: string,
selector: any,
listener: any,
subscribeOptions: any
) => {
if (key === 'state') {
// @ts-expect-error -- typescript is unable to infer the 3 args version
return store.subscribe(selector, listener, subscribeOptions);
}

let wrappedSelector: any;

if (listener) {
// subscribe(selector, listener, subscribeOptions) variant
wrappedSelector = (state: StateType) =>
selector(state[key as keyof StateType]);
} else {
// subscribe(listener) variant
listener = selector;
wrappedSelector = (state: StateType) => state[key as keyof StateType];
}

// @ts-expect-error -- typescript is unable to infer the 3 args version
return store.subscribe(wrappedSelector, listener, subscribeOptions);
};

const isMutative =
isMutativeState ||
_immerOptionsInternal.enabled ||
Expand Down Expand Up @@ -157,6 +185,7 @@ export const createStore = <
get: getFn,
name,
set: setFn,
subscribe: subscribeFn,
store,
useStore: store,
useValue,
Expand Down
Loading
Loading