response-router + antD/Как выделить элемент меню при нажатии кнопки "Назад/Перемотка вперед"?

Я создаю меню и хочу выделить элемент, который я выбираю, и я сделал это. Но когда я нажимаю кнопку назад/вперед, пункт меню не выделяется. Что мне делать?

Я попытался использовать addEventListener, но не смог.

Попросить кого-нибудь дать совет?

class Sidebar extends React.Component {
    constructor(props) {
        super(props);
        this.state={
            test: "home"
        }
        this.menuClickHandle = this.menuClickHandle.bind(this);
    }

    componentWillMount(){
        hashHistory.listen((event)=>{
            test1 = event.pathname.split("/");
        });
        this.setState({
            test:test1[1]
        });
    }

    menuClickHandle(item) {
        this.props.clickItem(item.key);
    }

    onCollapseChange() {
        this.props.toggle();
    }

    render() {
        var {collapse} = this.props;
        return (
            <aside className="ant-layout-sider">
                <Menu mode="inline" theme="dark" defaultSelectedKeys={[this.state.test || "home"]} onClick={this.menuClickHandle.bind(this)}>
                    <Menu.Item key="home">
                        <Link to="/home">
                            <Icon type="user"/><span className="nav-text">用户管理</span>
                        </Link>
                    </Menu.Item>
                    <Menu.Item key="banner">
                        <Link to="/banner">
                            <Icon type="setting"/><span className="nav-text">Banner管理</span>
                        </Link>
                    </Menu.Item>
                </Menu>
                <div className="ant-aside-action" onClick={this.onCollapseChange.bind(this)}>
                    {collapse ? <Icon type="right"/> : <Icon type="left"/>}
                </div>
            </aside>
        )
    }
}

Ответ 1

Перехватывает текущий URL-адрес и затем устанавливает selectedKeys (обратите внимание, что это не defaultSelectedKeys).

componentWillMount(){
        hashHistory.listen((event)=>{
            pathname = event.pathname.split("/");
            if(pathname != null){
                this.setState({
                    test:pathname[1]
                });
            }
        });
    }

Ответ 2

Я мог бы найти решение с помощью WithRouter

import React,{ Component } from 'react';
import { NavLink, withRouter } from 'react-router-dom';
import { Layout, Menu, Icon } from 'antd';
import PropTypes from 'prop-types';

const { Sider } = Layout;

class SideMenu extends Component{

  static propTypes = {
    location: PropTypes.object.isRequired
  }

  render() {
    const { location } = this.props;
    return (
        <Sider
          trigger={null}
          collapsible
          collapsed={this.props.collapsed}>

          <div className="logo" />
          <Menu
            theme="dark"
            mode="inline"
            defaultSelectedKeys={['/']}
            selectedKeys={[location.pathname]}>
            <Menu.Item key="/">
              <NavLink to="/">
                <Icon type="home" />
                <span>Home</span>
              </NavLink>
            </Menu.Item>
            <Menu.Item key="/other">
              <NavLink to="/other">
                <Icon type="mobile"/>
                <span>Applications</span>
              </NavLink>
            </Menu.Item>
            <Menu.Item key="/notifications">
              <NavLink to="/notifications">
                <Icon type="notification" />
                <span>Notifications</span>
              </NavLink>
            </Menu.Item>
          </Menu>
        </Sider>
    )
  }
}

export default withRouter(SideMenu);

Ответ 3

Вы можете установить пути ссылки в качестве ключей в каждом Menu.Item. затем selectedKeys = {this.props.location.pathname}

<Menu
  theme="light"
  mode='inline'
  selectedKeys={[this.props.location.pathname,]}
>
  <Menu.Item key={item.path} style={{float:'right'}}>
    Link to={item.path}>{item.name}</Link>
  </Menu.Item>
  {menulist}
</Menu>

Элемент будет активирован в соответствии с текущим путем. я добавил [] и завершающую запятую, потому что selectedKeys принимает массив, а this.props.location.pathname является строкой. я просто пишу как хобби, поэтому я не знаю, приемлемо ли это.

Ответ 4

Решение @Nadun работает для путей, которые не содержат аргументов. Однако, если вы используете аргументы в своих маршрутах, как я, вот решение, которое должно работать для любого пути маршрута, включая /users/:id или сумасшедшие вещи, такие как /users/:id/whatever/:otherId. Он использует реагирующий маршрутизатор API matchPath, который использует ту же логику, что и компонент Router.

// file with routes
export const ROUTE_KEYS = {
    ROOT: "/",
    USER_DETAIL: "/users/:id",
};

export const ROUTES = {
    ROOT: {
        component: Home,
        exact: true,
        key: ROUTE_KEYS.ROOT,
        path: ROUTE_KEYS.ROOT,
    },
    USER_DETAIL: {
        component: Users,
        key: ROUTE_KEYS.USER_DETAIL,
        path: ROUTE_KEYS.USER_DETAIL,
    },
};

.

// place within the App component
<Router>
    <Layout>
        <MyMenu />
        <Layout>
            <Layout.Content>
                {Object.values(ROUTES).map((route) => (
                    <Route {...route} />
                ))}
            </Layout.Content>
        </Layout>
    </Layout>
</Router>

.

// MyMenu component
const getMatchedKey = (location) =>
    (
        Object.values(ROUTES).find((route) =>
            matchPath(location.pathname, route)
        ) || {}
    ).path;

const MyMenu = ({ location }) => {
    return (
        <Layout.Sider>
            <AntMenu mode="inline" selectedKeys={[getMatchedKey(location)]}>
                <AntMenu.SubMenu
                    title={
                        <React.Fragment>
                            <Icon type="appstore" />
                            Home
                        </React.Fragment>
                    }
                >
                    <AntMenu.Item key={ROUTE_KEYS.ROOT}>
                        <Icon type="appstore" />
                        <span className="nav-text">
                            Some subitem
                        </span>
                    </AntMenu.Item>
                </AntMenu.SubMenu>
                <AntMenu.SubMenu
                    title={
                        <React.Fragment>
                            <Icon type="user" />
                            Users
                        </React.Fragment>
                    }
                >
                    <AntMenu.Item key={ROUTE_KEYS.USER_DETAIL}>
                        <Icon type="user" />
                        <span className="nav-text">
                            User detail
                        </span>
                    </AntMenu.Item>
                </AntMenu.SubMenu>
            </AntMenu>
        </Layout.Sider>
    );
};

export default withRouter(MyMenu);

Ответ 5

Я делаю что-то подобное, но это не похоже на реактивность. Например, если я перейду к новой странице с помощью кнопки (а не из пунктов меню), она не обновит активную ссылку до тех пор, пока страница не обновится.

import React from 'react';
import { StyleSheet, css } from 'aphrodite'
import { browserHistory, Link } from 'react-router';
import 'antd/lib/menu/style/css';
import 'antd/lib/icon/style/css';
import 'antd/lib/row/style/css';
import 'antd/lib/col/style/css';
import 'antd/lib/message/style/css';
import { appConfig } from '../../modules/config';
import { Menu, Icon, Row, Col, message } from 'antd';

const SubMenu = Menu.SubMenu;
const MenuItemGroup = Menu.ItemGroup;


const { appName } = appConfig;




const AppNavigation = React.createClass({
  getInitialState() {
        return {
          current: this.props.pathname
        };

  },
  handleClick(e) {
    browserHistory.push(e.key);
    this.setState({ current: e.key });
    return;  
  },
  render() {
    return (
    <Row className='landing-menu' type="flex" justify="space-around" align="middle"  style={{height: 55, zIndex: 1000, paddingLeft: 95, color: '#fff', backgroundColor: '#da5347', borderBottom: '1px solid #e9e9e9'}}>
        <Col span='19'>
            <Link to='/'>
          <h2 style={{fontSize: 21, color: '#fff'}}>
            {appName}
            <Icon type="rocket" color="#fff" style={{fontWeight: 200, fontSize: 26, marginLeft: 5 }}/>
          </h2>
        </Link>
        </Col>
        <Col span='5'>
            <Menu onClick={this.handleClick} selectedKeys={[this.state.current]} mode="horizontal" style={{height: 54, backgroundColor: '#da5347', borderBottom: '0px solid transparent'}}>
            <Menu.Item style={{height: 54, }} key="/">Home</Menu.Item>
            <Menu.Item style={{height: 54, }} key="/signup">Signup</Menu.Item>
            <Menu.Item style={{height: 54, }} key="/login">Login</Menu.Item>
          </Menu>
        </Col>

      </Row>
    );
  },
});


export const App = React.createClass({

  propTypes: {
    children: React.PropTypes.element.isRequired,
  },
  componentWillMount(){
    if (Meteor.userId()) {
      browserHistory.push('/student/home')
    }
  },
  render() {

    return (
        <div style={{position: 'relative'}}>
          <AppNavigation pathname={this.props.location.pathname}  />
            <div style={{minHeight: '100vh'}}>
             { this.props.children }
            </div>
        </div>
    );
  }





});

РЕДАКТИРОВАТЬ:

ниже работает очень хорошо. пропустите путь от ответного маршрутизатора и поп, который в качестве опоры в selectedKeys

import React from 'react';
import { StyleSheet, css } from 'aphrodite'
import { browserHistory, Link } from 'react-router';
import 'antd/lib/menu/style/css';
import 'antd/lib/icon/style/css';
import 'antd/lib/row/style/css';
import 'antd/lib/col/style/css';
import 'antd/lib/message/style/css';
import { appConfig } from '../../modules/config';
import { Menu, Icon, Row, Col, message } from 'antd';

const SubMenu = Menu.SubMenu;
const MenuItemGroup = Menu.ItemGroup;


const { appName } = appConfig;




const AppNavigation = React.createClass({
  getInitialState() {
        return {
          current: this.props.pathname
        };

  },
  handleClick(e) {
    browserHistory.push(e.key);
    this.setState({ current: e.key });
    return;  
  },
  render() {
    return (
    <Row className='landing-menu' type="flex" justify="space-around" align="middle"  style={{height: 55, zIndex: 1000, paddingLeft: 95, color: '#fff', backgroundColor: '#da5347', borderBottom: '1px solid #e9e9e9'}}>
        <Col span='19'>
            <Link to='/'>
          <h2 style={{fontSize: 21, color: '#fff'}}>
            {appName}
            <Icon type="rocket" color="#fff" style={{fontWeight: 200, fontSize: 26, marginLeft: 5 }}/>
          </h2>
        </Link>
        </Col>
        <Col span='5'>
            <Menu onClick={this.handleClick} selectedKeys={[this.props.pathname]} mode="horizontal" style={{height: 54, backgroundColor: '#da5347', borderBottom: '0px solid transparent'}}>
            <Menu.Item style={{height: 54, }} key="/">Home</Menu.Item>
            <Menu.Item style={{height: 54, }} key="/signup">Signup</Menu.Item>
            <Menu.Item style={{height: 54, }} key="/login">Login</Menu.Item>
          </Menu>
        </Col>

      </Row>
    );
  },
});


export const App = React.createClass({

  propTypes: {
    children: React.PropTypes.element.isRequired,
  },
  componentWillMount(){
    if (Meteor.userId()) {
      browserHistory.push('/student/home')
    }
  },
  render() {

    return (
        <div style={{position: 'relative'}}>
          <AppNavigation pathname={this.props.location.pathname}  />
            <div style={{minHeight: '100vh'}}>
             { this.props.children }
            </div>
        </div>
    );
  }


});