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

[v3] remove _handleSet from _TemporalState #154

Merged
merged 3 commits into from
Mar 10, 2024

Conversation

pstrassmann
Copy link
Collaborator

@pstrassmann pstrassmann commented Jan 19, 2024

This PR removes the _handleSet internal property of _TemporalState in favor of defining handleSet within temporal (index.ts).

This is beneficial from a complexity-reducing standpoint: _handleSet no longer needs to be a member of the temporal state, and its functionality is easily discoverable and readable within temporal.

This change also allows us to remove the type assertion required for accessing private internal properties of _TemporalState when using getState(), which returns type TemporalState.

@charkour
Copy link
Owner

Ah, I see the issue. This is a really annoying part of zustand and I don't know the best practice. I'll make a discussion on the zustand repo to see what the problem is.

I think the tests are failing due to a bug. We override the set callback in the wrapTemporal test but not the store.setState. If you add store.setState = set; right before returning the config, that should "fix" the tests. I think it's expected the middleware modify both, but I need to check with the zustand maintainers.

image

@charkour charkour self-assigned this Jan 20, 2024
@charkour
Copy link
Owner

Made the discussion here: pmndrs/zustand#2305

@pstrassmann
Copy link
Collaborator Author

Ah okay thank you for this! To make sure I understand, is the potential bug of directly modifying setState due to the fact that if multiple nested middlewares do this, setState will just be identical to the last middleware-defined set function instead of applying all nested middleware's set functionality? Or is it that if not all middleware's modify setState, set and setState would differ? I may also still be a little confused...

@charkour
Copy link
Owner

Or is it that if not all middleware's modify setState, set and setState would differ?

Yup, exactly! If the user of the middleware expects that set and setState behave the same, then it's an issue.

Looking at this more, I think we'll want to move forward with this change, but it'll have to be for v3 because it's a breaking change. It depends on setState rather than set.

@charkour charkour changed the base branch from main to v3 January 21, 2024 19:00
@pstrassmann pstrassmann changed the title [WIP] refactor: remove _handleSet from _TemporalState refactor: remove _handleSet from _TemporalState (v3) Jan 22, 2024
@pstrassmann
Copy link
Collaborator Author

Ok sounds good! I updated the tests with your suggested fixes, which indeed stopped the tests from failing. If there's anything else you'd like me to do with this PR, just let me know.

@pstrassmann pstrassmann changed the title refactor: remove _handleSet from _TemporalState (v3) [v3] remove _handleSet from _TemporalState Jan 22, 2024
@@ -700,6 +701,7 @@ describe('Middleware options', () => {
},
1000,
);
store.setState = set;
Copy link
Owner

Choose a reason for hiding this comment

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

Hey @pstrassmann, sorry for the delay. Life has been busy and I haven't made time for working on v3 of zundo; however, I'm here now after some good discussions in the zustand repo regarding authoring middleware.

Before merging this in, could you add another test case where store.setState = set isn't added and we expect .toHaveBeenCalled(0)? To put it in English, we should have a test case for zundo, there wrapTemporal fails to be called because we haven't modified the store setter.

src/index.ts Outdated
currentState,
);
store.temporal.setState({
...store.temporal.getState(),
Copy link
Owner

Choose a reason for hiding this comment

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

Why is this line needed here? Shouldn't we only need to be passing pastStates and futureStates here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I (mistakenly, I think) was under the impression that setState did not do the kind of auto-merging of state that set does, which is why I spread the other values here. I will remove this line.

Copy link
Owner

Choose a reason for hiding this comment

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

Gotcha, thanks. I think they both behave the same.

Comment on lines +643 to +663
it('should not call function if `store.setState` is not assigned to `set` (wrapTemporal)', () => {
global.console.info = vi.fn();
const storeWithHandleSet = createVanillaStore({
wrapTemporal: (config) => {
return (_set, get, store) => {
const set: typeof _set = (partial, replace) => {
console.info('handleSet called');
_set(partial, replace);
};
// intentionally commented out
// store.setState = set;
return config(set, get, store);
};
},
});
const { increment } = storeWithHandleSet.getState();
act(() => {
increment();
});
expect(console.info).toHaveBeenCalledTimes(0);
});
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Please feel free to suggest a better test description, or if you'd prefer the commented out lines to be removed

Copy link
Owner

Choose a reason for hiding this comment

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

Awesome, thank you!

Copy link
Owner

@charkour charkour left a comment

Choose a reason for hiding this comment

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

Thanks for the great work on this!

@charkour charkour merged commit ca8209b into charkour:v3 Mar 10, 2024
3 checks passed
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.

None yet

2 participants