Skip to content

Commit

Permalink
feat: add support for shallow state merging
Browse files Browse the repository at this point in the history
  • Loading branch information
StyleShit committed Jul 5, 2024
1 parent a93b08a commit 7e5594f
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/spicy-monkeys-march.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"zusdux": patch
---

Add support for shallow state merging
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ First, you create a store with the `createStore` function. It takes an object wi
- `initialState` - It's... well... the _initial state_ of your store

- `actions` - An object containing a list of actions that can be performed on the state. The actions can be either synchronous or asynchronous, they can take any
number of arguments, while the first one is a `set` function that allows you to update the store's state
number of arguments, while the first one is a `set` function that allows you to update the store's stat. The `set` function can accept either a new state object
that will be shallowly merged with the current state, or a function that receives the current state and returns the new state.
(See [Zustand](https://docs.pmnd.rs/zustand/guides/updating-state)'s documentation for more info)

```ts
// store.ts
Expand Down Expand Up @@ -65,10 +67,7 @@ export const { actions, getState, setState, subscribe, useStore } = createStore(
},

setName: (set, firstName: string, lastName: string) => {
set((prev) => ({
...prev,
name: firstName + ' ' + lastName,
}));
set({ name: firstName + ' ' + lastName });
},
},
},
Expand Down
20 changes: 15 additions & 5 deletions src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ describe('Zusdux', () => {
name: 'counter',
count: 5,
});

// Act.
setState({ count: 10 });

// Assert.
expect(getState()).toStrictEqual({
name: 'counter',
count: 10,
});
});

it('should change the state using actions', () => {
Expand Down Expand Up @@ -222,7 +231,11 @@ describe('Zusdux', () => {
expectTypeOf(getState).toEqualTypeOf<() => ExpectedState>();

expectTypeOf(setState).toEqualTypeOf<
(setter: (prevState: ExpectedState) => ExpectedState) => void
(
setterOrState:
| ((prevState: ExpectedState) => ExpectedState)
| Partial<ExpectedState>,
) => void
>();

expectTypeOf(useStore).toEqualTypeOf<
Expand Down Expand Up @@ -259,10 +272,7 @@ function createCounter() {
},

setName: (set, firstName: string, lastName: string) => {
set((prev) => ({
...prev,
name: firstName + ' ' + lastName,
}));
set({ name: firstName + ' ' + lastName });
},
},
});
Expand Down
7 changes: 5 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ export function createStore<

const getState = () => state;

const setState: SetState<S> = (setter) => {
state = setter(state);
const setState: SetState<S> = (setterOrState) => {
state =
typeof setterOrState === 'function'
? setterOrState(state)
: { ...state, ...setterOrState };

notify();
};
Expand Down
4 changes: 3 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ export type ParseActions<
: never;
};

export type SetState<S> = (setter: (prevState: S) => S) => void;
export type SetState<S> = (
setterOrState: ((prevState: S) => S) | Partial<S>,
) => void;

0 comments on commit 7e5594f

Please sign in to comment.