React Material UI BottomNavigation组件浏览器路由状态同步问题
这个问题的核心是你的BottomNavigation组件只在点击导航项时手动更新了选中状态,但没有监听路由的变化——当用户使用浏览器前进/后退按钮时,路由路径已经改变,但组件完全没感知到,自然就出现了状态不一致的情况。下面给你两种可行的解决方案,推荐第一种更简洁的路由驱动方式:
方案一:完全由路由驱动选中状态(推荐)
这种方式不需要组件自己维护selectedIndex状态,直接根据当前路由路径计算选中项,从根源上避免状态不同步。
修改你的MyBottomNavigation组件:
import React, { Component } from 'react'; import { withRouter } from 'react-router'; import { browserHistory } from 'react-router'; import Paper from 'material-ui/Paper'; import BottomNavigation from 'material-ui/BottomNavigation'; import BottomNavigationItem from 'material-ui/BottomNavigation/BottomNavigationItem'; // 记得导入你的图标组件 import recentsIcon from './path-to-recents-icon'; import favoritesIcon from './path-to-favorites-icon'; import nearbyIcon from './path-to-nearby-icon'; class MyBottomNavigation extends Component { // 根据当前路由路径计算选中索引 getSelectedIndex = () => { const { pathname } = this.props.location; switch(pathname) { case '/courses': return 1; case '/authors': return 2; default: return 0; } } selectBottomNavigationItem(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() { const selectedIndex = this.getSelectedIndex(); return ( <Paper zDepth={1}> <BottomNavigation selectedIndex={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> ) } } // 用withRouter包裹组件,才能获取到路由location属性 export default withRouter(MyBottomNavigation);
方案二:监听路由变化更新组件状态
如果你需要保留组件内部状态(比如有特殊业务需求),可以通过监听路由变化来同步更新selectedIndex:
import React, { Component } from 'react'; import { withRouter } from 'react-router'; import { browserHistory } from 'react-router'; import Paper from 'material-ui/Paper'; import BottomNavigation from 'material-ui/BottomNavigation'; import BottomNavigationItem from 'material-ui/BottomNavigation/BottomNavigationItem'; // 导入图标组件 import recentsIcon from './path-to-recents-icon'; import favoritesIcon from './path-to-favorites-icon'; import nearbyIcon from './path-to-nearby-icon'; class MyBottomNavigation extends Component { constructor(props){ super(props) // 初始化时根据路由设置选中索引 this.state = { selectedIndex: this.getSelectedIndex() } this.selectBottomNavigationItem = this.selectBottomNavigationItem.bind(this) } getSelectedIndex = () => { const { pathname } = this.props.location; switch(pathname) { case '/courses': return 1; case '/authors': return 2; default: return 0; } } // 组件挂载时初始化状态 componentDidMount() { this.setState({ selectedIndex: this.getSelectedIndex() }); } // 监听路由变化,更新选中状态 componentDidUpdate(prevProps) { if (prevProps.location.pathname !== this.props.location.pathname) { this.setState({ selectedIndex: this.getSelectedIndex() }); } } 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 withRouter(MyBottomNavigation);
两种方案都能实现点击导航项、浏览器前进后退时,BottomNavigation的选中索引和当前路由完全同步,第一种方案更简洁,也减少了状态维护的成本,优先推荐使用。
内容的提问来源于stack exchange,提问作者Derek
相关产品推荐
相关产品推荐

