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

createActions helper #224

Open
theKashey opened this issue Mar 11, 2024 · 2 comments
Open

createActions helper #224

theKashey opened this issue Mar 11, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@theKashey
Copy link

With actions being defined aside of createStore it might become a little tricky to type them.

In many cases one had to write something like

const actions = {
    resetTriggerPosition: (): Action<State> => () => ({ setState }) => {
            setState({  });
        },
}

The modern way to write the same with less TS involved can use satisties operator

const actions = {
    resetTriggerPosition: () => () => ({ setState }) => {
            setState({  });
        },
}  satisfies Record<
    string,
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    (...args: any[]) => Action<State>
>;

Works, but is it making anything better?


what about creating a helper function createActions in the form of

const createActions =<TState extends object>(): <TActions extends Record<string, ActionThunk<TState, TActions>>(actions: TActions): TActions => actions;

That simple, the same interface as createStore accepts.

This fill change action definition to

```tsx
const actions = createActions<State>()({
    resetTriggerPosition: () => () => ({ setState }) => {
            setState({  });
        },
} )

Something like https://www.typescriptlang.org/play?#code/ATCWDsBcFMCcDMCGBjawDK1LsomAeAFRz2gD5gBvAKBBAApxoB3EmALmAAVFZJREAGyJtyASk4A3APagAJgG5awAL7VlkAJ4AHNAHEsokbhgUAvMHpjgZigCVoiOdPCDNx0mSUadaHNNhoAEFkfhcg7VAPUxsqZRAAZ0MTaE5MbBTo8iU6YABzZNJOAwzSLK944DlQBO08ZAALTiJgaAAPGHA5BOAQsPAsgBpgRHBNYdHNMjJ6SpAUfsIGgFdwAGtOQkrrW2AHSGXYcEJfIgqQFW8QLV1e0NAXfEriFMHngGEXXAg4LlhpbQ9CwyeRvXKEfaHcAANSEyzQwNkcmAAB9uP8ALY1aD4EFyMjKcyWSqISJpSABYL3cKRcpgujIL6IH6wP4AhKbT5QZlMVn-QHKHYUCFYKGwwTwq7AG5oPoPY4rdZPcGiekgQhylw9dqdbp7aCM2ByfAJSCwCB5YaahWrNZDYAa6ngBLTQmxegAOi9vDyHJGYyFd369smEzGFWojOdkGAyECpGtQKyrQ60C6PWkACMAFYGyAzCTAIiJlO6noOQ3G03m8CWoPypa2+2O-ou6b0Bbyv0truBzta7xR03S6DDixxxwwRP4ShtdjVi0qAv0GjXUeQdhWEC7FdJUowFSBveiFdzgCMw007AATIfqIeFEA

Wondering if with modern TS we can remove the first function call, it "bind" State variable.

@albertogasparin
Copy link
Collaborator

While I wouldn't mind such API, there has been questions around the constrain of bundling of too many actions on store creation, and the fact that such pattern could not only increase bundle size but also cause unnecessary circular imports.

So, if we were to think of some better APIs for actions, I would probably move towards decomposing them and making them a per-hook:

const store = createStore({ initialState }); // no actions
const useMyStore = createHook(store, { actions: ... }); // specific per hook

or via dispatch like API at the consumer location:

import { action, useMyStoreAction } from './my-store'
// ... inside the component
const triggerChange = useMyStoreAction(action);

or

import { useDispatch } from 'react-sweet-state'
import { store, action } from './my-store'
// ... inside the component
const triggerChange = useAction(store, action);

or

import { useMyStore, action } from './my-store'
// ... inside the component
const [state, dispatch] = useMyStoreViaDispatch();
const triggerChange = () => dispatch(action(...))

The benefit of forcing the import of the action on the consumer side is that it makes more explicit the dependency.
The per-hook pattern can be a good way to enable this decomposition when needed, while the dispatch exposes a bit more of the implementation detail... Unsure about the best path forward.

@albertogasparin albertogasparin added the enhancement New feature or request label Mar 17, 2024
@theKashey
Copy link
Author

Splitting actions from state was always my first preference, but I dont see a good usecase with action being "reused" for multiple stores. This defines the "type flow" as store -> action, which is roughly the opposite of the current configuration.
Ie option 1 and 2, but not 3 and 4 are they cause "store to meet action" in the user space.

// option 1.5, right in the middle of 1 and 2
const useMyStore = createHook(store, action);

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

No branches or pull requests

2 participants