Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[@xstate/store] v3 #5175

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open

[@xstate/store] v3 #5175

wants to merge 16 commits into from

Conversation

davidkpiano
Copy link
Member

No description provided.

Copy link

changeset-bot bot commented Jan 22, 2025

🦋 Changeset detected

Latest commit: 80fe593

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@xstate/store Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

davidkpiano and others added 3 commits January 21, 2025 21:29
- Added `StoreEffect` type to support both emitted events and side effects.
- Updated `createStoreTransition` to return effects instead of emitted events.
- Modified `receive` function to handle effects, executing functions or emitting events accordingly.
- Added a test case to verify that effects can be enqueued and executed after state updates.

This change improves the flexibility of the store's event handling mechanism.
@davidkpiano davidkpiano marked this pull request as ready for review January 25, 2025 13:32
- Updated `createStore` and `createStoreWithProducer` to use more explicit type parameters
- Replaced `types: { emitted }` with separate type parameters for context, event payloads, and emitted events
- Removed `Cast` import and simplified type definitions
- Updated test cases to use new type parameter approach
- Added `EventMap` type to support event type mapping
Comment on lines 13 to 18
// Sent events
{
inc: {
by: number;
};
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the need for this explicit slot is a significant DX downgrade, but I guess you have already made up your mind on this. It feels like this now uses different set of tradeoffs than setup from xstate which is somewhat weird, even if both libraries are not strictly related.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need this if you're not using emitted events; it's still inferred. But if you are, this:

createStore({
  types: {
    emitted: {} as ...
  },
  // …
});

is also not really a good DX.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll change this since this is now inferred

}

export const createStore: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are going with "Type parameters should now be explicitly provided to createStore and createStoreWithProducer" then those overloads are not needed at all here and this could be just simplified/inlined

Comment on lines 14 to 18
{
inc: {
by: number;
};
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This payload map doesn't feel like an ergonomic explicit type argument - you won't need it anywhere else than at the createStore call. A union plays better with other utils you might want to build around this API as a user. Like, even a logEvent becomes much more cumbersome to type because you need to somehow extract the event type from your store instead of just using the same union type that you could use here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The payload map is mostly to still allow for inference when the type parameters are not provided.


expect(store.getSnapshot().context.count).toEqual(1);

await new Promise((resolve) => setTimeout(resolve, 10));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can import a shared util for this instead:

import { sleep } from '@xstate-repo/jest-utils';

@@ -144,17 +147,16 @@ it('createStoreWithProducer(…) works with an immer producer (object API)', ()
});

it('createStoreWithProducer(…) infers the context type properly with a producer', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test should be removed now, it was specifically testing the non-object API. A test for the object API is directly below this one an it's the only one that you need after deprecating and removing the previous API

@expelledboy
Copy link

expelledboy commented Feb 1, 2025

Oh no... 😭 #5183

Figuring out how to pass the types around was difficult. But I think I made some improvements, even beyond the new getter API.

But when I saw how many changes where in this PR... I am going to get a beer.

@davidkpiano
Copy link
Member Author

Oh no... 😭 #5183

Figuring out how to pass the types around was difficult. But I think I made some improvements, even beyond the new getter API.

But when I saw how many changes where in this PR... I am going to get a beer.

Hey @expelledboy – computed properties are a great idea! I think you'll find the types even simpler to work with in this PR. Let's make it work. 🛠️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants