React Material UI BottomNavigation 组件路由问题

Posted

技术标签:

【中文标题】React Material UI BottomNavigation 组件路由问题【英文标题】:React Material UI BottomNavigation component Routing Issue 【发布时间】:2018-07-04 18:07:25 【问题描述】:

我正在尝试从 Material UI 实现底部导航组件,但我在用户使用浏览器的后退和前进按钮时遇到了问题。

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

我留下的是一个不一致的状态。

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

这是 UI 的外观:-

[

这是根组件:-

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

【问题讨论】:

我的情况完全相同。如果我找到解决方案,我会发布答案。 【参考方案1】:

刚刚实现了一个工作!

诀窍是制作一个新的导航栏组件,该组件包装 Material UI BottomNavigation 并使用 react-router-domwithRouter 高阶函数将其导出。然后你可以对传入 props 的当前路由进行一些摆弄,并根据路由数组(哪个路由对应哪个值)设置BottomNavigation 组件的值。

我的代码与您最初发布的代码有些不同,我只是从BottomNavigation 示例here 和react-router-dom here 的使用示例中脱离出来。

这是我的实现:

/src/App.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;
/src/components/PrimaryNav.js
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);

这是我的版本号:

"@material-ui/core": "^1.3.1",
"@material-ui/icons": "^1.1.0",
"react": "^16.4.1",
"react-dom": "^16.4.1",

【讨论】:

【参考方案2】:

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

基本上你只需在每次渲染时创建一个pathname 常量,使用window.location.pathname 并确保每个&lt;BottomNavigationAction /&gt; 的值属性设置为与路由相同(包括前面的正斜杠)......类似:

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。

【讨论】:

【参考方案3】:

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

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

【讨论】:

react-router-dom 没有NavigationLink 组件。 对不起,我是说 NavLink reactrouter.com/web/api/NavLink

以上是关于React Material UI BottomNavigation 组件路由问题的主要内容,如果未能解决你的问题,请参考以下文章

在 Material-UI 中使用 React 的 'ref' 属性

Material Design UI素材库React版--定制

React + Material-UI |如何创建水平滚动卡片?

为 SelectField 显示空白菜单项的正确方法是啥(material-ui,react)

React Material-UI 网格系统 [重复]

React中Material-Ui中增加标签的问题