How to use Redux to represent Material UI Drawer?

Viewed 734

I am trying to implement Drawer, which will appear on the left with a saving state of the Drawer using Redux. But unfortunately, I did something wrong and my onClick events just don`t respond. Code:
Reducer:

import { NEW_DATA_LOADED, DRAWER_TOGGLED } from '../actions/types';
import { initialState } from '../store';

export default function rootReducer(state = initialState, action) {
    console.log(state);
    console.log(action);
    switch (action.type) {
        case DRAWER_TOGGLED: {
            return { categories: state.categories, authors: state.authors, articles: state.articles, drawerToggled: action.value };
        }
        case NEW_DATA_LOADED: {
            const keyValue = action.keyValue;
            const content = action.content;
            console.log(action);
            let newState = { categories: state.categories, authors: state.authors, articles: state.articles, drawerToggled: state.drawerToggled };;
            newState[keyValue] = content;
            return newState;
        }
        default:
            return state;
    }
}


creators.js:

import { NEW_DATA_LOADED, DRAWER_TOGGLED } from "./types";

const newDataLoaded = (key, content) => ({ type: NEW_DATA_LOADED, content: content, keyValue: key });
const drawerToggled = (open) => ({ type: DRAWER_TOGGLED, value:open });

export { newDataLoaded , drawerToggled };

store.js:

import { createStore, compose, applyMiddleware } from "redux";
import rootReducer from './reducers/root';
import ReduxThunk from 'redux-thunk';

const initialState = { articles:[], authors:[],categories:[],  drawerToggled: false };

export default function configStore() {
  return createStore(
    rootReducer,
    initialState,
    compose(
      applyMiddleware(ReduxThunk),
      window.devToolsExtension ? window.devToolsExtension() : f => f
    )
  );
}
export { initialState };


And NavBar.js:

import React from 'react';
import { AppBar, Toolbar } from '@material-ui/core';
import FaceIcon from '@material-ui/icons/Face';
import MenuIcon from '@material-ui/icons/Menu';
import IconButton from 'material-ui/IconButton';
import Drawer from "@material-ui/core/Drawer";
import ListItem from "@material-ui/core/ListItem";
import List from "@material-ui/core/List";
import makeStyles from "@material-ui/styles/makeStyles";
import { BrowserRouter as Router } from "react-router-dom";
import ListItemText from "@material-ui/core/ListItemText";
import BackToTopButton from "../BackToTopButton/BackToTopButton";
import { connect } from 'react-redux';
import { toggleDrawer } from '../../actions';
import './NavBar.css';


const useStyles = makeStyles(theme => ({
    list: {
        width: 250
    },
    fullList: {
        width: "auto"
    },
    paper: {
        background: "#485461"
    }
}));
function NavBar(props){
        const toolbar = React.createRef();
        let toolbarElement = props.article === true ? <Toolbar id="back-to-top-anchor" ref={toolbar} /> : <Toolbar />;
        let button = null;
        if (props.article === true) {
            button = <BackToTopButton anchor={toolbar} />;
        }
        const classes  = useStyles;
        const navbar_links = [["Home", "/"], ["Categories", "/categories"], ["Interesting Posts For You", "/interesting"], ["Your Inbox", "/inbox"], ["Register account","/registration"]];
        const sideList = (
            <div className={classes.list} role="presentation" onClick={props.toggleDrawer(false)}
                onKeyDown={props.toggleDrawer(false)}>
                <List>
                    {navbar_links.map((text) => (
                        <ListItem component="a" button key={text[0]} href={text[1]}>
                            <ListItemText>{text[0]}</ListItemText>
                        </ListItem>
                    ))}
                </List>
            </div>
        );
    const toggleDrawer = (open) => { props.toggleDrawer(open) };
    const drawerToggled = props.drawerToggled;
        return (
            <React.Fragment>
                <Router>
                    <AppBar position="sticky">
                        <Toolbar>
                            <IconButton className={"menu"} aria-label="Menu" color="white"
                                onClick={toggleDrawer(true)}>
                                <MenuIcon />
                            </IconButton>
                            <Drawer
                                classes={{ paper: classes.paper }}
                                open={drawerToggled}
                                onClose={toggleDrawer(false)}
                            >
                                <div
                                    tabIndex={0}
                                    role="button"
                                    onClick={toggleDrawer(false)}
                                    onKeyDown={toggleDrawer(false)}
                                    className={{ root: classes.root }}
                                >
                                    {sideList}
                                </div>
                            </Drawer>

                            <section className={"rightToolBar"}>
                                <IconButton className={"profile"} aria-label="My profile" color={"black"} href="/profile">
                                    <FaceIcon />
                                </IconButton>
                            </section>
                        </Toolbar>
                    </AppBar>
                    {toolbarElement}
                </Router>
                {button}
            </React.Fragment>
        );
    }

const mapStateToProps = (state) => ({
    drawerToggled:state.drawerToggled
});
const mapDispatchToProps = (dispatch) => ({
    toggleDrawer: (open) => dispatch(toggleDrawer(open)),
});

export default connect(mapStateToProps, mapDispatchToProps)(NavBar);


P.S. Version of this navbar, implemented with react state worked good, so the problem is somewhere in redux usage.
Can anyone help me to make it work? CodeSandbox:
https://codesandbox.io/s/github/LilJohny/BlogUI/tree/develop_4

2 Answers

From the code, toggleDrawer in mapDispatchToProps should actually be drawerToggled in creators like this:

toggleDrawer: (open) => dispatch(drawToggled(open)),

You might want to rename the variable to match what you have in mapDispatchToProps, to avoid confusion.

If this is doesn't fix your problem, maybe setting up a codesandbox will help people troubleshoot your problem better.

Related