Hi,
I'm trying to create a vue composable hook to toggle sidebar menu.
import { reactive, toRefs } from '@vue/composition-api';
const useToggleMenu = () => {
const state = reactive({
isMenuOpen: true,
});
const toggleMenu = () => {
state.isMenuOpen = !state.isMenuOpen;
};
return {
...toRefs(state),
toggleMenu,
};
};
export default useToggleMenu;
the problem I'm facing is when using isMenuOpen
state in one component (ex: Layout), and use toggleMenu
in another component (ex: BurgerMenu).
// BurgerMenu.vue
import { useToggleMenu } from '../hooks';
export default {
name: 'BurgerMenu',
setup() {
const { toggleMenu } = useToggleMenu();
return {
// use this in template to show/hide menu.
toggleMenu,
};
},
...
};
// Layout.vue
import { useToggleMenu } from '../hooks';
export default {
name: 'Layout',
setup() {
const { isMenuOpen } = useToggleMenu();
return {
// use this in template to add some classes to <body>
isMenuOpen,
};
},
};
...
};
the issue is when I click burger menu and trigger the toggleMenu
function, that does not make any change! the isMenuOpen
boolean is not reactive.
I hope that is clear, and thanks to anyone trying to help.
Top comments (4)
Do you mean it is not reactive that the state doesn't sync between your
BurgerMenu.vue
and in yourLayout.vue
? That is correct. Each time you calluseToggleMenu()
you basically create your own scope of that function, so they can run in parallel without interfering with eachother.Check this codesandbox to see what I mean:
Codesandbox
Here I copied your code. I only changed the
reactive
toref
because a single value is better suited in aref()
. As you can see here the code is reactive but the two implementations do not sync.Also you do not need to put the state in
toRefs()
when returningThank you Alex,
Yes i now understand what's the problem,
I need to put some mechanism to share that state between those components. something like
useContext
in React.jsNormally you can just move the state out of the function.
Something like
Not tested but this should work I think
Hi!
The problem is that every time you call it, your composable is creating a new scope. There are many ways to solve this problem.
You can use the composable on a component that is parent of Layout and BurgerMenu, then pass props to them and emit events for the parent to execute the changes on the state.
Another way is to using provide/inject, this is kinda similar to useContext in react.
Sorry if my english is not good enough.
Good luck!