React Material UI BottomNavigation组件路由问题

时间:2018-01-25 13:16:40

标签: reactjs react-router material-ui

我试图从Material UI实现BottomNavigation组件,但是当用户使用浏览器的后退和前进按钮时我遇到了问题。

问题是,BottomNavigation组件配置为在按下导航项按钮时更改布局中的页面。但是,当浏览器用于返回上一页时,它不会改变BottomNavigation项目的选定索引。

我剩下的是一种不一致的状态。

如何在使用浏览器按钮时更改导航组件的选定索引?

以下是UI的外观: -

[Material UI Layout[1]

以下是根组件: -

import React from 'react'
import {browserHistory, withRouter} from 'react-router';
import {PropTypes} from 'prop-types'
import {connect} from 'react-redux'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
import AppBar from 'material-ui/AppBar'
import Paper from 'material-ui/Paper'
import MyBottomNavigation from '../material-ui/MyBottomNavigation'

const style = {
    padding: 10,
    height: '85vh'

  }

class Root extends React.Component {
    constructor(props) {
        super(props)   

        this.state  = {
            bottomNavItemIndex : 0
        }
    }


    render() {
        return (
            <MuiThemeProvider>
                <div>
                    <AppBar title="Pluralsight Admin" 
                        iconClassNameRight="muidocs-icon-navigation-expand-more"
                        showMenuIconButton={false}
                        zDepth={1}
                        />
                    <Paper zDepth={1} style={style}>
                        {this.props.children}
                    </Paper>
                    <MyBottomNavigation/>
                </div>
            </MuiThemeProvider>

        )
    }
}


Root.propTypes = {
    children: PropTypes.object.isRequired
}



export default Root

这是导航组件: -

class MyBottomNavigation extends Component {
    constructor(props){
        super(props)
        this.state = {
            selectedIndex: 0
          }

        this.selectBottomNavigationItem = this.selectBottomNavigationItem.bind(this)
    }

  selectBottomNavigationItem(index){
    this.setState({selectedIndex: index})

    switch(index) {
        case 0:
        return browserHistory.push('/')
        case 1:
        return browserHistory.push('/courses')
        case 2:
        return browserHistory.push('/authors')
        default:
        return browserHistory.push('/')
    }
  }


  render() {
    return (
      <Paper zDepth={1}>
        <BottomNavigation selectedIndex={this.state.selectedIndex}>

          <BottomNavigationItem
            label="Home"
            icon={recentsIcon}
            onClick={() => this.selectBottomNavigationItem(0)}
          />

          <BottomNavigationItem
            label="Course"
            icon={favoritesIcon}
            onClick={() => this.selectBottomNavigationItem(1)}
          />

          <BottomNavigationItem
            label="Authors"
            icon={nearbyIcon}
            onClick={() => this.selectBottomNavigationItem(2)}
          />
        </BottomNavigation>
      </Paper>
    )
  }
}


export default MyBottomNavigation

3 个答案:

答案 0 :(得分:5)

只是实现了工作!

诀窍是制作一个新的导航栏组件,该组件将包装材质UI BottomNavigation,并使用react-router-dom的{​​{1}}高阶函数将其导出。然后,您可以对当前传递到props中的路由进行一些修改,并根据一组路由(哪个路由对应哪个值)来设置withRouter组件的值。

我的代码与您最初发布的代码有些不同,我只是使用BottomNavigation示例hereBottomNavigation here的用法示例

这是我的实现方式:

/src/App.js
react-router-dom
/src/components/PrimaryNav.js
import React, {Component} from 'react';
import './App.css';
import {BrowserRouter as Router, Route} from 'react-router-dom';
import PrimaryNav from './components/PrimaryNav';

// Views
import HomeView from './views/HomeView';

class App extends Component {
  render() {
    return (
      <Router>
        <div className="app">
          <Route path="/" component={HomeView} />        
          <PrimaryNav />
        </div>
      </Router>
    );
  }
}

export default App;

下面是我的版本号,以供参考:

import React, {Component} from 'react';
import {Link, withRouter} from 'react-router-dom';
import BottomNavigation from '@material-ui/core/BottomNavigation';
import BottomNavigationAction from '@material-ui/core/BottomNavigationAction';
import LanguageIcon from '@material-ui/icons/Language';
import GroupIcon from '@material-ui/icons/Group';
import ShoppingBasketIcon from '@material-ui/icons/ShoppingBasket';
import HelpIcon from '@material-ui/icons/Help';
import EmailIcon from '@material-ui/icons/Email';
import './PrimaryNav.css';

class PrimaryNav extends Component {
  state = {
    value: 0,
    pathMap: [
      '/panoramas',
      '/members',
      '/shop',
      '/about',
      '/subscribe'
    ]
  };

  componentWillReceiveProps(newProps) {
    const {pathname} = newProps.location;
    const {pathMap} = this.state;

    const value = pathMap.indexOf(pathname);

    if (value > -1) {
      this.setState({
        value
      });
    }
  }

  handleChange = (event, value) => {
    this.setState({ value });
  };

  render() {
    const {value, pathMap} = this.state;

    return (
      <BottomNavigation
        value={value}
        onChange={this.handleChange}
        showLabels
        className="nav primary"
      >
        <BottomNavigationAction label="Panoramas" icon={<LanguageIcon />} component={Link} to={pathMap[0]} />
        <BottomNavigationAction label="Members" icon={<GroupIcon />} component={Link} to={pathMap[1]} />
        <BottomNavigationAction label="Shop" icon={<ShoppingBasketIcon />} component={Link} to={pathMap[2]} />
        <BottomNavigationAction label="About" icon={<HelpIcon />} component={Link} to={pathMap[3]} />
        <BottomNavigationAction label="Subscribe" icon={<EmailIcon />} component={Link} to={pathMap[4]} />
      </BottomNavigation>
    );
  }
}

export default withRouter(PrimaryNav);

答案 1 :(得分:1)

刚刚为这个 here 找到了一个非常巧妙的解决方案:

本质上,您只需在每次渲染时创建一个 pathname 常量,使用 window.location.pathname 并确保每个 <BottomNavigationAction /> 的 value prop 设置为与路由相同(包括前面的正斜杠) ...类似:

const pathname = window.location.pathname
const [value, setValue] = useState(pathname)
const onChange = (event, newValue) => {
    setValue(newValue);
}
return (
    <BottomNavigation className={classes.navbar} value={value} onChange={onChange}>
        <BottomNavigationAction component={Link} to={'/'} value={'/'} label={'Home'} icon={<Home/>} />
        <BottomNavigationAction component={Link} to={'/another-route'} value={'/another-route'} label={'Favourites'} icon={<Favorite/>} />
    </BottomNavigation>
)

这意味着 value 的初始状态始终取自当前 URL。

答案 2 :(得分:0)

我认为您应该避免对此组件进行内部状态管理。如果您需要了解并突出显示当前选择的路线,则可以仅使用react-router-dom中的NavigationLink而不是Link。 “活动”类将添加到相应的元素。如果只希望在检测到精确匹配时才激活导航元素,则只需注意确切的道具即可。

[更新]我输入了错误的组件名称,即NavLink,而不是NavigationLink。我的错。这是指向文档https://reactrouter.com/web/api/NavLink

的链接