VueJS + Vuex + Vuetify Navigation Drawer - javascript

I have a page with a toolbar and a sidebar. The sidebar is only visible when a user is logged in.
The sidebar Navigation Drawer is default not visible if the user is on a mobile device.
Now i want a button in the toolbar that the user can open the sidebar.
But the toolbar and the sidebar are two different components.
Therefore i'm using Vuex to manage the state. But the state is computet and has no setter, so i can't use the state direct in the navigaion controllers v-model.
Now i read that you can define a get and a set method on computed variables.
But is this the best way to do this?

in your template:
<template>
<v-navigation-drawer
:value="isHomeNavigationDrawerOpen"
#input="TOGGLE_HOME_NAVIGATION_DRAWER"
...>
</v-navigation-drawer>
</template>
<scripts>
import { mapState, mapActions } from 'vuex'
export default {
computed: {
...mapState('userData', ['user', 'loggedIn']),
...mapState('toolbar', ['isHomeNavigationDrawerOpen']),
},
methods:{
...mapActions('toolbar', ['TOGGLE_HOME_NAVIGATION_DRAWER']),
}
...
In your store module toolbar.js (or your module name)
export default {
state: {
isHomeNavigationDrawerOpen: null,
},
actions: {
TOGGLE_HOME_NAVIGATION_DRAWER(context, open) {
context.commit('TOGGLE_HOME_NAVIGATION_DRAWER', open)
},
},
mutations: {
TOGGLE_HOME_NAVIGATION_DRAWER: (state, open) => {
state.isHomeNavigationDrawerOpen = open
},
},
}

In Vuetify, the component v-navigation-drawer emit a event called 'input' used by v-model.
This event is emitted when the navigation drawer is displayed and when it is closed. If we call the 'toggle' function in both cases we will enter an infinite loop.
I have the same problem and it is what is happening to me.

The way vuex want you to do is to use the proper state mutation.
#click="$store.commit('open-sidebar')"
And the computed value will react to the mutation.

On your toolbar component, this is where you want your button; Define a drawer boolean property. The html with the button in the toolbar component would look something like this:
<v-toolbar color="primary" dark app :clipped-left="$vuetify.breakpoint.mdAndUp" fixed>
<v-toolbar-side-icon #click.stop="$emit('update:drawer', !drawer)"></v-toolbar-side-icon>
In the toolbar component parent you would also want to declare an drawer variable. Then the html would look something like this:
<toolbar :drawer.sync="drawer"></toolbar>
<v-navigation-drawer class="secondary" dark fixed :clipped="$vuetify.breakpoint.mdAndUp" app v-model="drawer">
toolbar is your toolbar component which I mentioned earlier.
You will note that the navigation drawer is now listening to the drawer property.
Please let me know if this answer is not suffice, I will create an example for you

Related

While using useMediaQuery hook, getting error: Rendered more hooks than during previous render

I am trying to hide a tooltip on mobile devices. For this, I am using useMediaQuery to detect the width like this:
const isMobile = useMediaQuery({ query: '(max-width: 767px)' })
Then I am passing isMobile to a ReactTooltip component as the prop disabled.
<ReactTooltip disable={isMobile} id="favouriteMeeting" place="bottom" effect="solid">
Make Favourite
</ReactTooltip>
But whenever I click on a meeting, I am getting this error -
Rendered more hooks than during the previous render
. What am I doing wrong? Please help!

Why does my React app menu open when I am only changing the state and am not using any CSS?

I have a button in my Header component. When it is clicked, it calls a toggleNav function stored in my context.js. This function changes the state of isNavOpen from false to true. The navgiation then opens. There is no CSS in my project that should allow this behavior. I also don't see any JS code that should allow this behavior either. Could someone tell me what code allows my navigation to open and close?
My codesandbox
This is down to the basic way that React works, when you change the state of a component, it re-renders itself with the new values you've set into state.
Specifically it's this bit of Header.js:
{context.state.isNavOpen && (
<div className="js-nav nav">
...
When the component renders the first time, context.state.isNavOpen is false, and false && anything is still false, so javascript ignores the code after the &&. That means it skips over the menu code.
The second time it renders, after you update the state which is pushed to context and then passed to <Header> as a prop (!), the component re-renders with your menu code.
If you use your browser's dev tools to inspect the DOM before and after you click the button, you'll find that the menu isn't hidden and shown, but rather when you don't see it, it's gone from the DOM altogether.
It's react feature whenever state changes component re-renders
same thing happening here
{context.state.isNavOpen && (
isNavOpen is toggling (true to false), (false to true)
for example - you can check it simply
class Toggle extends React.Component {
state = {
visibility: false
}
toggleVisibility=()=>{
this.setState(prev=>({visibility:!prev.visibility}))
}
render() {
const {visibility} = this.state;
return (
<div>
<button onClick={this.toggleVisibility}>Click Me</button>
<h3>{visibility?'Welcome':''}</h3>
</div>
);
}
};

Unmount inactive screens (reset stacks) in bottom tab navigator

Im using react-navigation v3, is there an option to make that inactive tab screens get unmounted like unmountInactiveRoutes: true in DrawerNavigator?? I cant find something like unmountInactiveRoutes for BottomTabNavigator.
I have two stacknavigators inside a BottomTabNavigator and I want to unmount them automatically or just reset them.
my navigators:
BottomTabNavigator
stackNavigator
stackNavigator
You can use the useIsFocused hook to solve your problem. So when the screen is focused you will display your desirable screen otherwise just return null. Check the code below:
import { useIsFocused } from '#react-navigation/native';
const isFocused = useIsFocused();
if(isFocused) return(/*your screen*/)
else if(!isFocused) return null
And if you want to make some fetching or some changes on every focus just use the useFocusEffect hook.

React Material-UI: open dialog by button (in higher level) with createRef not working with using 'withMobileDialog'

In my demo here https://codesandbox.io/s/zq833pq6o3
you can open one dialog(Child-Dialog) in two different ways.
by an button who is in this dialog (Button: OPEN BY THIS)
by an button from the parent level (Button: OPEN BY REF)
But the same case is not working with my Login-Dialog in the App-Bar.
The difference between both cases is i'm using
import withMobileDialog from "#material-ui/core/withMobileDialog";
...
export default withMobileDialog()(LoginDialog);
// instead of normal way: export default LoginDialog;
in my Login-Dialog
Button: LOGIN => is working and open the Login-Dialog
Button: LOGIN REF => is not working and i get the error:
TypeError
_this.dialogRef.current.handleClickOpen is not a function
How can i fix the ref-Problem? By changing the export command?
the same problems are also by using of
export default withStyles(styles)(LoginForm);
// instead of: export default LoginForm;
thanks!

React re-rendering modal component

I have 2 modal windows which I have defined as react components. As soon as the user on our sites click on a button, the first modal renders and indicates that some processing is happening. We are making some API calls while this modal is processing. Based on the results of the API call, I need to be able to replace this modal with another modal window that has some other content in it. Currently this is the code I have, but this does not render the second modal window.
import React, { PropTypes, Component } from 'react';
import * as statusList from './status';
class AppStatus extends Component {
static propTypes = {
component: PropTypes.string
}
render() {
const { component, ...statusProps } = this.props;
const Status = statusList[component];
return (
<div id="app-status" className="expanded row align-center align-middle">
<Status {...statusProps} />
</div>
);
}
}
export default AppStatus;
The behavior I am seeing is that the first modal shows first, when the second component has to render the modal completely disappears.
What am I am doing wrong here? How do I make this render?

Categories