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

feat: create useState composable #1402

Merged
merged 8 commits into from
Feb 13, 2024
37 changes: 32 additions & 5 deletions packages/x-components/src/composables/use-store.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,40 @@
import { getCurrentInstance } from 'vue';
import { computed, ComputedRef, getCurrentInstance } from 'vue';
import { Store } from 'vuex';
import { Dictionary } from '@empathyco/x-utils';
import { ExtractState, XModuleName } from '../x-modules/x-modules.types';

/**
* Function which returns the `$store` object from the current component instance.
* Function which returns the `$store` object from the current component instance
* and the selected state as a dictionary of paths.
*
* @returns The `$store` object from the current component instance.
* @param module - The {@link XModuleName} of the getter.
* @returns The state properties of the module and the `$store`.
*
* @public
*/
export function useStore(): Store<any> {
return (getCurrentInstance()?.proxy as { $store: Store<any> }).$store;
export function useStore<Module extends XModuleName, Path extends keyof ExtractState<Module>>(
module?: Module
): UseStore<Module, Path> {
const store = (getCurrentInstance()?.proxy as { $store: Store<any> }).$store;
const useState = (module: Module, paths: Path[]): ComputedRef<Dictionary<keyof Path>> => {
return paths.reduce<ComputedRef<Dictionary<keyof Path>>>((state, path) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
state[path] = computed(() => store.state.x[module][path]);
return state;
}, {} as ComputedRef<Dictionary<keyof Path>>);
};
const useStateWithModule = useState.bind(module);
return {
store,
useState: module ? useStateWithModule : useState
};
}

Copy link
Contributor

Choose a reason for hiding this comment

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

The types for the useStore are wrong. We don't have a ComputedRef of a Dictionary but the other way around. It should be something like:

type UseStore = {
  store: Store<any>;
  useState: <Module extends XModuleName, Paths extends keyof ExtractState<Module>>(
    module: Module,
    paths: Paths[]
  ) => Dictionary<ComputedRef>;
};

export function useStore(): UseStore {
  const store = (getCurrentInstance()?.proxy as { $store: Store<any> }).$store;
  const useState = <Module extends XModuleName, Paths extends keyof ExtractState<Module>>(
    module: Module,
    paths: Paths[]
  ): Dictionary<ComputedRef> => {
    return paths.reduce<Dictionary<ComputedRef>>((state, path) => {
      state[path as string] = computed(() => store.state.x[module][path]);
      return state;
    }, {});
  };
  return {
    store,
    useState
  };

For this first iteration I would skip the use case of passing the module as argument.

/**
* Return type of the {@link useStore} composable.
*/
type UseStore<Module extends XModuleName, Path extends keyof ExtractState<Module>> = {
store: Store<any>;
useState: (module: Module, paths: Path[]) => ComputedRef<Dictionary<keyof Path>>;
};
Loading