基于当前路径在React Router+Material UI中设置导航激活状态的实现问题
你当前的选中状态仅通过点击事件更新本地state维护,无法和浏览器URL同步,刷新、直接访问路径、前进后退都会出现状态不一致的问题,直接和路由的实际路径绑定即可实现自动激活效果,有两种常用实现方案:
方案1:使用useLocation钩子匹配路径(推荐,逻辑最直观)
- 从react-router-dom中导入
useLocation钩子,获取当前页面的实际路径 - 直接用当前路径和导航项的path做匹配,不需要额外维护selectedIndex状态和点击更新逻辑
完整代码修改示例:
import {BrowserRouter as Router, Route, Link, Switch, useLocation} from 'react-router-dom'; // 组件内获取当前路径 const location = useLocation(); // 原来的selectedIndex、handleListItemClick可以直接删除,不需要手动维护 // 渲染导航逻辑 {data && data.navigation.map((item, i) => <Link key={i} to={`${item.path}`} className={classes.link}> <ListItem button // 直接用当前路径和导航项路径匹配,根路径需要精确匹配避免误判 selected={location.pathname === item.path} > <ListItemText className={classes.navLink}>{item.label}</ListItemText> </ListItem> </Link> )}
方案2:使用React Router内置的NavLink组件
NavLink本身内置了路径激活状态判断,不需要手动获取路径:
import {BrowserRouter as Router, Route, Switch, NavLink} from 'react-router-dom'; // 渲染导航逻辑 {data && data.navigation.map((item, i) => <NavLink key={i} to={`${item.path}`} className={classes.link}> {/* NavLink的children支持传入函数,直接获取当前激活状态给ListItem使用 */} {({ isActive }) => ( <ListItem button selected={isActive}> <ListItemText className={classes.navLink}>{item.label}</ListItemText> </ListItem> )} </NavLink> )}
注意事项
如果存在嵌套路由的场景,可以把匹配逻辑改成location.pathname.startsWith(item.path),同时给根路径加额外判断避免一直被命中。
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

