我有一个用React + Redux和Antdesign编写的应用程序。我的应用程序是一个仪表板应用程序。所以我在Ant设计https://ant.design/components/layout/
中使用了布局当我单击侧面菜单时,活动菜单会变为粗体,这很好。但是当我刷新页面时,我需要它检查并检测路线和与粗体相关的菜单项。
我有一个状态为 Sidebar 的组件。在它里面,在componentDidMount中,我调用了一个函数,该函数将从mapDispatchToProps调度一个动作。减速器改变状态。但是在HTML代码中,在defaultSelectedKeys中,我无法设置活动菜单的数量。
Sidebar.js组件:
import React from 'react';
import { render } from 'react-dom';
import { connect } from 'react-redux'
import { Switch, BrowserRouter, Route, Link } from 'react-router-dom';
// antd
import { Layout, Breadcrumb, Menu, Icon } from 'antd';
const { Header, Content, Footer, Sider } = Layout;
// Helpers
import { Alert } from '../helpers/notifications';
// Components
import Home from '../components/Home';
// import Header from '../components/Header';
import NotFound from '../components/NotFound';
import PostsEditor from '../components/Posts/PostsEditor';
// Actions
import { setRouteActiveFlag } from '../actions/ui.action'
class Sidebar extends React.Component {
componentDidMount () {
const routes = {
'/' : 1,
'/posts' : 2,
'/logout' : 3
}
this.props.detectActiveRoute(setRouteActiveFlag({
routes:routes,
path:window.location.pathname
}))
}
render() {
const { selectedRoute } = this.props;
console.log(selectedRoute);
return (
<div>
<Layout>
<Sider
style={{
overflow: 'auto',
height: '100vh',
position: 'fixed',
left: 0,
}}
breakpoint="lg"
collapsedWidth="0"
onBreakpoint={broken => {
console.log(broken);
}}
onCollapse={(collapsed, type) => {
console.log(collapsed, type);
}}
>
<div className="logo" >
Logo <br/><br/><br/>
</div>
<Menu theme="dark" mode="inline" style={{ lineHeight: '64px' }} defaultSelectedKeys={[selectedRoute.toString() || '1']}>
<Menu.Item key="1">
<Link to="/" style={{ color:'#fff' }}>
<Icon type="user" />
<span className="nav-text">Home</span>
</Link>
</Menu.Item>
<Menu.Item key="2">
<Link to="/posts" style={{ color:'#fff' }}>
<Icon type="user" />
<span className="nav-text">Posts</span>
</Link>
</Menu.Item>
<Menu.Item key="3">
<a href="/logout" style={{ color:'#fff' }}>
<Icon type="user" />
<span className="nav-text">Logout</span>
</a>
</Menu.Item>
</Menu>
</Sider>
<Layout style={{ marginLeft: 200 }}>
<Content style={{ margin: '24px 16px 0', overflow: 'initial'}}>
<Breadcrumb style={{ margin: '0 0 20px 0' }}>
<Breadcrumb.Item>Home</Breadcrumb.Item>
<Breadcrumb.Item>List</Breadcrumb.Item>
<Breadcrumb.Item>App</Breadcrumb.Item>
</Breadcrumb>
<div style={{ padding: 24, background: '#fff', minHeight: 360 }}>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/posts/:id?" component={PostsEditor} />
<Route component={NotFound}/>
</Switch>
<Alert stack={ { limit: 3 } } />
</div>
</Content>
<Footer style={{ textAlign: 'center' }}>Ant Design ©2018 Created by Ant UED</Footer>
</Layout>
</Layout>
</div>
);
}
}
const mapStateToProps = (state, ownProps) => {
return {
state: state,
props: ownProps,
selectedRoute:state.ui.selectedRoute || 1
}
}
const mapDispatchToProps = (dispatch, ownProps) => {
return {
detectActiveRoute: (obj) => dispatch(obj)
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Sidebar)
ui.action.js
export const setRouteActiveFlag = (payload = 'global') => ({
type: actions.SET_ROUTE_ACTIVE_FLAG,
payload
});
ui.reducer.js
import { handleActions } from 'redux-actions';
import Immutable from 'seamless-immutable';
import * as actions from '../consts/action-types';
const initialState = Immutable({
requests: {},
selectedRoute:{}
});
export default handleActions({
[actions.SET_ROUTE_ACTIVE_FLAG]: (state, action) => {
if (action.payload.routes && action.payload.path && action.payload.routes[ action.payload.path ]) {
return state.set('selectedRoute', action.payload.routes[ action.payload.path ])
}else{
return state.set('selectedRoute', 1)
}
}
}, initialState);
请帮助我找到最佳和简单的做法。
答案 0 :(得分:2)
无需使用redux
,只需使用react-router
获取当前路径名并将其传递给defaultSelectedKeys
。
<Menu defaultSelectedKeys={[this.props.location.pathname]}>
...
.....
</Menu>
如果您不知道如何获取路径名,请查看此answer
答案 1 :(得分:1)
以下答案假定您正在使用钩子。我知道从您的问题来看,您没有使用钩子,但对其他人可能有用。此答案不仅适用于刷新,而且适用于按向后和向前按钮:
import React, { useState, useEffect } from 'react'
import { useHistory, useLocation } from 'react-router-dom'
import { Layout, Menu } from 'antd'
const { Sider } = Layout
const items = [
{ key: '1', label: 'Invoices', path: '/admin/invoices' },
{ key: '2', label: 'Service Details', path: '/admin/service-details' },
{ key: '3', label: 'Service Contract Details', path: '/admin/service-contract-details' },
{ key: '4', label: 'Cost Centers', path: '/admin/cost-centers' },
{ key: '5', label: 'Clients', path: '/admin/clients' },
{ key: '6', label: 'Vendors', path: '/admin/vendors' }
]
const Sidebar = () => {
const location = useLocation()
const history = useHistory()
const [selectedKey, setSelectedKey] = useState(items.find(_item => location.pathname.startsWith(_item.path)).key)
const onClickMenu = (item) => {
const clicked = items.find(_item => _item.key === item.key)
history.push(clicked.path)
}
useEffect(() => {
setSelectedKey(items.find(_item => location.pathname.startsWith(_item.path)).key)
}, [location])
return (
<Sider style={{ backgroundColor: 'white' }}>
<h3 style={{ paddingLeft: '1rem', paddingTop: '1rem', fontSize: '1.25rem', fontWeight: 'bold', minHeight: 64, margin: 0 }}>
Costek
</h3>
<Menu selectedKeys={[selectedKey]} mode='inline' onClick={onClickMenu}>
{items.map((item) => (
<Menu.Item key={item.key}>{item.label}</Menu.Item>
))}
</Menu>
</Sider>
)
}
export default Sidebar
您的侧边栏将如下所示:
答案 2 :(得分:0)
您可以通过调节并以这种方式添加类来在菜单中添加任何CSS。
<MenuItem className={ (this.props.location.pathname==='/yourRoute')? 'active' : '' } >
</MenuItem>
如果您遇到任何类型的未定义错误,则可以使用“ withRouter” HOC
以这种方式。
在要获取该位置道具的组件中,您将首先导入
import {withRouter} from 'react-router-dom';
然后您可以通过这种方式将其导出。
export default withRouter(YourComponent);
最终代码看上去与此类似
import React, {Fragment, Component} from 'react';
import {withRouter, Link } from 'react-router-dom';
class Menu extends Component {
render(){
const {pathname} = this.props.location;
return (
<Fragment>
<div id="sidebar-menu" className="sidebar-menu">
<ul>
<li className={(pathname==='/dashboard' || pathname==='/')?'active':''}>
<Link to="/dashboard">Dashboard</Link>
</li>
<li className={(pathname==='/properties')?'active':''}>
<Link to="/properties">Properties</Link>
</li>
</ul>
</div>
</Fragment>
);
}
}
export default withRouter(Menu);