Повторное отображение в компоненте об изменении состояния в Redux Store - PullRequest
0 голосов
/ 18 января 2019

Я хотел показать кнопку выхода из системы после входа пользователя в систему и скрыть видимость кнопки после выхода пользователя из системы. Пункты меню поступают из файла Menu.js.

Текущий рабочий процесс приложения: если пользователь вошел в систему, состояние хранилища обновляется в хранилище, на основе этого состояния я хочу показать кнопку выхода из системы в Меню.

Состояние авторизации корректно обновляется в хранилище Redux при входе в систему, и я могу получить значение auth в файле Menu.js из хранилища Redux, но изменение не отображается в Siderbar.js, пока я не обновлю страницу. Что мне нужно сделать в sidebar.js, чтобы получить меню об изменении состояния авторизации в Store.

Siderbar.js

<pre><code>
import React, { Component } from 'react';
import { withNamespaces, Trans } from 'react-i18next';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Link, withRouter } from 'react-router-dom';
import { Collapse, Badge } from 'reactstrap';
import SidebarRun from './Sidebar.run';
import SidebarUserBlock from './SidebarUserBlock';

import Menu from '../../Menu';

/** Component to display headings on sidebar */
const SidebarItemHeader = ({item}) => (
    <li className="nav-heading">
        <span><Trans i18nKey={item.translate}>{item.heading}</Trans></span>
    </li>
)

/** Normal items for the sidebar */
const SidebarItem = ({item, isActive}) => (
    <li className={ isActive ? 'active' : '' }>
        <Link to={item.path} title={item.name}>
            {item.label && <Badge tag="div" className="float-right" color={item.label.color}>{item.label.value}</Badge>}
            {item.icon && <em className={item.icon}></em>}
            <span><Trans i18nKey={item.translate}>{item.name}</Trans></span>
        </Link>
    </li>
)

/** Build a sub menu with items inside and attach collapse behavior */
const SidebarSubItem = ({item, isActive, handler, children, isOpen}) => (
    <li className={ isActive ? 'active' : '' }>
        <div className="nav-item" onClick={ handler }>
            {item.label && <Badge tag="div" className="float-right" color={item.label.color}>{item.label.value}</Badge>}
            {item.icon && <em className={item.icon}></em>}
            <span><Trans i18nKey={item.translate}>{item.name}</Trans></span>
        </div>
        <Collapse isOpen={ isOpen }>
            <ul id={item.path} className="sidebar-nav sidebar-subnav">
                { children }
            </ul>
        </Collapse>
    </li>
)

/** Component used to display a header on menu when using collapsed/hover mode */
const SidebarSubHeader = ({item}) => (
    <li className="sidebar-subnav-header">{item.name}</li>
)

class Sidebar extends Component {

    state = {
        collapse: {},
        isLoggedIn: ''
    }

    componentDidMount() {
        // pass navigator to access router api
        SidebarRun(this.navigator.bind(this));
        // prepare the flags to handle menu collapsed states
        this.buildCollapseList()
    }

    /** prepare initial state of collapse menus. Doesnt allow same route names */
    buildCollapseList = () => {
        let collapse = {};

        Menu
            .filter(({heading}) => !heading)
            .forEach(({name, path, submenu}) => {
                collapse[name] = this.routeActive(submenu ? submenu.map(({path})=>path) : path)
            })
        this.setState({collapse});
    }

    navigator(route) {
        this.props.history.push(route);
    }

    routeActive(paths) {
        paths = Array.isArray(paths) ? paths : [paths];
        return paths.some(p => this.props.location.pathname.indexOf(p) > -1)
    }

    toggleItemCollapse(stateName) {
        for (let c in this.state.collapse) {
            if (this.state.collapse[c] === true && c !== stateName)
                this.setState({
                    collapse: {
                        [c]: false
                    }
                });
        }
        this.setState({
            collapse: {
                [stateName]: !this.state.collapse[stateName]
            }
        });
    }

    getSubRoutes = item => item.submenu.map(({path}) => path)

    /** map menu config to string to determine what element to render */
    itemType = item => {
        if (item){
        // console.log(item)
            if (item.heading) return 'heading';
            if (!item.submenu) return 'menu';
            if (item.submenu) return 'submenu';
    }}

    render() {
        return (
            <aside className='aside-container'>
                { /* START Sidebar (left) */ }
                <div className="aside-inner">
                    <nav data-sidebar-anyclick-close="" className="sidebar">
                        { /* START sidebar nav */ }
                        <ul className="sidebar-nav">
                            { /* START user info */ }
                            <li className="has-user-block">
                                <SidebarUserBlock/>
                            </li>
                            { /* END user info */ }

                            { /* Iterates over all sidebar items */ }
                            {
                                Menu.map((item, i) => {
                                    // heading
                                    if(this.itemType(item) === 'heading')
                                        return (
                                            <SidebarItemHeader item={item} key={i} />
                                        )
                                    else {
                                        if(this.itemType(item) === 'menu')
                                            return (
                                                <SidebarItem isActive={this.routeActive(item.path)} item={item} key={i} />
                                            )
                                        if(this.itemType(item) === 'submenu')
                                            return [
                                                <SidebarSubItem item={item} isOpen={this.state.collapse[item.name]} handler={ this.toggleItemCollapse.bind(this, item.name) } isActive={this.routeActive(this.getSubRoutes(item))} key={i}>
                                                    <SidebarSubHeader item={item} key={i}/>
                                                    {
                                                        item.submenu.map((subitem, i) =>
                                                            <SidebarItem key={i} item={subitem} isActive={this.routeActive(subitem.path)} />
                                                        )
                                                    }
                                                </SidebarSubItem>
                                            ]
                                    }
                                    return null; // unrecognized item
                                })
                            }
                        </ul>
                        { /* END sidebar nav */ }
                    </nav>
                </div>
                { /* END Sidebar (left) */ }
            </aside>
        );
    }
}

Sidebar.propTypes = {
    isLoggedIn: PropTypes.object.isRequired
};
const mapStateToProps = (state, ownProps) => {
    // console.log("Sidebar: ", state.auth);
    return{
        isLoggedIn: state.auth,
}}

export default connect(mapStateToProps)(withRouter(Sidebar));

Что мне делать в Sidebar.js, чтобы он заново отображал меню при изменении состояния авторизации.

Любая помощь будет принята с благодарностью.

Файл Menu.js



    import configureStore from './store/store';
    const store = configureStore();

    function select(state) {
        return state.auth
    }

        let loggedIn = select(store.getState());

        let Meu = [

        {
            name: 'Analytics',
            icon: 'icon-speedometer',
            translate: 'sidebar.nav.DASHBOARD',
            submenu: [{
                    name: 'Overview',
                    path: '/dashboard',
                    translate: 'sidebar.nav.element.HOME'
                },
                {
                    name: 'Revenue',
                    path: '/revenue',
                    translate: 'sidebar.nav.element.REVENUE'
                },
                {
                    name: 'Source',
                    path: '/source',
                    translate: 'sidebar.nav.element.SOURCE'
                },
                {
                    name: 'Marketing',
                    path: '/marketing',
                    translate: 'sidebar.nav.element.MARKETING'
                }
            ]
        },
        {
            name: 'Tools',
            icon: 'fa fa-briefcase',
            translate: 'sidebar.nav.TOOLS',
            submenu: [
                {
                    name: 'Customer Service',
                    path: '/customer-service',
                    translate: 'sidebar.nav.element.CUSTOMER-SERVICE'
                }

            ]
        },

        {
            name: 'Settings',
            icon: 'icon-settings',
            translate: 'sidebar.nav.SETTINGS',
            submenu: [{
                    name: 'Profile Settings',
                    path: '/profile',
                    translate: 'sidebar.nav.element.PROFILE-SETTINGS'
                },
                {
                    name: 'Company Settings',
                    path: '/company-settings',
                    translate: 'sidebar.nav.element.SETTINGS'
                }
            ]
        },

        {(loggedIn.authResponse) ?
            ({
                name: 'Logoff',
                icon: 'icon-lock',
                path: '/logoff' 
            }) : null
        }
    ];
        const Menu = Meu.filter(word => word !== null) 
        export default (Menu)

1 Ответ

0 голосов
/ 18 января 2019

Внутри родительского компонента вашей кнопки выхода из системы вы можете условно отобразить кнопку выхода из системы; обратите внимание, это означает, что ваш родительский компонент подключен к редуксу через connect (mapStateToProps)

{ this.props.isLoggedIn ? <Button>Log Out</Button> : null }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...