-
Notifications
You must be signed in to change notification settings - Fork 21
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
feat: create useState composable #1402
Conversation
const state = computed((): ExtractState<Module>[Path] => { | ||
return $store.state.x[module][path]; | ||
}); | ||
return state.value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returning the value
instead of the computed property breaks the reactivity. Better to return the computed property directly.
const state = computed((): ExtractState<Module>[Path] => { | |
return $store.state.x[module][path]; | |
}); | |
return state.value; | |
return computed(() => $store.state.x[module][path]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!!
* @returns The state properties of the module. | ||
* @public | ||
*/ | ||
export function useState<Module extends XModuleName, Path extends keyof ExtractState<Module>>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What was the reason to create a new standalone composable instead of extending the useStore
one? The task gave the two options, so I'm curious about the reasoning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No reason, I had forgotten that option.
const store = (getCurrentInstance()?.proxy as { $store: Store<any> }).$store; | ||
const state = computed(() => store.state.x[module][path]); | ||
return { | ||
store, | ||
state | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would break if both module
or path
are not passed to the composable.
Instead of this approach, I'm thinking of something closer to what vueblocks is doing:
https://vueblocks.github.io/vue-use-utilities/guide/vuex/useVuex.html#example
For our case, we should return store always and the composable can receive the module name as optional.
Instead of returning the state directly, we return a useState
function that receives the module and a list of paths to the state's properties. If the module name was provided when calling the useStore
composable then it's binded to the useState
function so it only needs the paths list
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉
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 | ||
}; | ||
} |
There was a problem hiding this comment.
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.
x: { | ||
namespaced: true, | ||
modules: { | ||
searchBox: { namespaced: true, ...searchBoxXStoreModule } as any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can type this part as AnyXStoreModule
searchBox: { namespaced: true, ...searchBoxXStoreModule } as any | |
searchBox: { namespaced: true, ...searchBoxXStoreModule } as AnyXStoreModule |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gj!
EMP-3458
Pull request template
Currently, we have a decorator @state that allows a component to read a piece of the state. We need to create a new composable that provides the same functionality.
We have created a reactive composable that returns a dictionary of the state of a list of params in a specific module.
Motivation and context
Type of change
What is the destination branch of this PR?
Main
How has this been tested?
To test it, I have created a
test
component where I use theuseState
composable to save the value in a computed variable. Then I updated (with the browser console) the store to test if the reactivity was working correctly.Test component:
Update store:
InterfaceX.setSnippetConfig({store: "Gijon"})
(display test component in the demo)
Checklist: