Я хотел показать кнопку выхода из системы после входа пользователя в систему и скрыть видимость кнопки после выхода пользователя из системы. Пункты меню поступают из файла 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)