React导航setState首次点击样式不更新 疑constructor自动重置状态
问题原因
你遇到的首次点击链接高亮不生效、二次点击才生效的问题,根源就是组件重挂载触发constructor重置状态:
- 你当前将
Nav组件放在各个路由页面内部引入,点击Link跳转路由时,旧路由页面卸载、新路由页面挂载,Nav组件会跟着被销毁后重新创建 - 组件重建时constructor会重新执行,
activeIndex被重置为初始值0,你第一次点击触发的setState修改的状态随旧组件销毁被清空,自然不会生效 - 当你已经跳转到目标页面后,再次点击同个链接不会触发路由跳转和组件重建,setState修改的状态能正常保留,所以高亮就生效了,和你观察到的现象完全吻合。
解决方案
方案一(推荐,无需手动维护状态)
直接使用react-router-dom内置的NavLink组件替代原生Link+自定义state的实现,组件会自动匹配当前路由地址,给激活的链接自动添加对应类名,从根源上避免状态重置问题,代码也更简洁。
修改后的Nav.js代码:
import React from 'react'; import { NavLink } from 'react-router-dom'; import LogOutLink from './LogOutLink'; import './Nav.scss'; class Nav extends React.Component { render() { return ( <> <ul> <li> <NavLink to='/search' className={({isActive}) => isActive ? 'link active' : 'link'} > SEARCH </NavLink> </li> <li> <NavLink to='/alldata' className={({isActive}) => isActive ? 'link active' : 'link'} > ALL DATA </NavLink> </li> <div style={{ float: 'right' }}><li><LogOutLink /></li></div> </ul> </> ); } } export default Nav;
如果你使用的是v5及更早版本的react-router-dom,可以用更简单的写法,直接指定激活类名即可:
// react-router-dom v5 适用 <NavLink to="/search" className="link" activeClassName="active">SEARCH</NavLink> <NavLink to="/alldata" className="link" activeClassName="active">ALL DATA</NavLink>
原有Nav.scss的样式代码不需要做任何修改,直接就能正常生效。
方案二(保留原有state逻辑)
如果要保留自己维护activeIndex状态的写法,只需要调整Nav组件的挂载位置:把Nav组件移到路由容器的外层,不要在各个路由页面内部单独引入,保证路由跳转时Nav组件不会被卸载重建,constructor只会在应用初始化时执行一次,setState修改的状态就不会被重置。
根组件参考结构:
function App() { return ( <div className="app-container"> {/* 导航放在路由外层,全程不会被卸载 */} <Nav /> <Routes> <Route path="/search" element={<SearchPage />} /> <Route path="/alldata" element={<AllDataPage />} /> {/* 其他路由配置 */} </Routes> </div> ) }
问题截图

内容的提问来源于stack exchange,提问作者user1461451
相关产品推荐
相关产品推荐

