React Router切换/india与/us路由页面数据不更新问题求助
React Router切换国家路由时页面数据不更新问题解决
问题描述
使用React Router开发时,其他路由导航功能正常,但从/india路由切换至/us路由,或反向切换时,页面数据无法更新。尝试过添加onclick事件、调用forceUpdate方法,均未解决问题。
相关代码
App.js
import React, { Component, useState } from "react"; import Navbar from './Components.js/Navbar' import News from "./Components.js/News"; import { Route, Routes, Navigate} from "react-router-dom"; export default function App() { return ( <> <Navbar/> <Routes> <Route exact path="/" element={<Navigate to="/india" replace={true} />}/> <Route exact path="/india" element={<News key="general" category="general" country="in"/>}/> <Route exact path="/india/entertainment" element={<News key="entertainment" category="entertainment" country="in"/>}/> <Route exact path="/india/sports" element={<News key="sports" category="sports" country="in"/>}/> <Route exact path="/india/business" element={<News key="business" category="business" country="in"/>}/> <Route exact path="/india/health" element={<News key="health" category="health" country="in"/>}/> <Route exact path="/india/science" element={<News key="science" category="science" country="in"/>}/> <Route exact path="/india/technology" element={<News key="technology" category="technology" country="in"/>}/> <Route exact path="/us" element={<News key="general" category="general" country="us"/>}/> <Route exact path="/us/entertainment" element={<News key="entertainment" category="entertainment" country="us"/>}/> <Route exact path="/us/sports" element={<News key="sports" category="sports" country="us"/>}/> <Route exact path="/us/business" element={<News key="business" category="business" country="us"/>}/> <Route exact path="/us/health" element={<News key="health" category="health" country="us"/>}/> <Route exact path="/us/science" element={<News key="science" category="science" country="us"/>}/> <Route exact path="/us/technology" element={<News key="technology" category="technology" country="us"/>}/> </Routes> </> ) }
Navbar.js
import React, { Component, useState } from "react"; import { Route, Routes, useLocation, useNavigate ,Redirect, Navigate} from "react-router-dom"; import { NavLink,Link } from "react-router-dom"; const Navbar=()=>{ const navigate = useNavigate(); const [cat,set_cat]=useState(""); const [country,set_country]=useState("india"); return ( <> <nav className="navbar navbar-expand-lg bg-body-tertiary"> <div className="container-fluid"> <a className="navbar-brand" to="#">Navbar</a> <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span className="navbar-toggler-icon"></span> </button> <div className="collapse navbar-collapse" id="navbarSupportedContent"> <ul className="navbar-nav me-auto mb-2 mb-lg-0"> <li className="nav-item" onClick={()=>set_cat("")}> <NavLink className="nav-link" to={`/${country}`}>HOME</NavLink> </li> {/* <li className="nav-item"><a className="nav-link" to="/about">About</a></li> */} <li className="nav-item" onClick={()=>set_cat("business")}><NavLink className="nav-link" to={`/${country}/business`}>BUSINESS</NavLink></li> <li className="nav-item" onClick={()=>set_cat("entertainment")}><NavLink className="nav-link" to={`/${country}/entertainment`}>ENTERTAINMENT</NavLink></li> <li className="nav-item" onClick={()=>set_cat("health")}><NavLink className="nav-link" to={`/${country}/health`}>HEALTH</NavLink></li> <li className="nav-item" onClick={()=>set_cat("science")}><NavLink className="nav-link" to={`/${country}/science`}>SCIENCE</NavLink></li> <li className="nav-item" onClick={()=>set_cat("sports")}><NavLink className="nav-link" to={`/${country}/sports`}>SPORTS</NavLink></li> <li className="nav-item" onClick={()=>set_cat("technology")}><NavLink className="nav-link" to={`/${country}/technology`}>TECHNOLOGY</NavLink></li> <li className="nav-item" onClick={()=>{navigate('/india'); set_country("india"); }}><Link className="nav-link" to={`/india`}>India</Link></li> <li className="nav-item" onClick={()=>{navigate('/us'); set_country("us"); }}><Link className="nav-link" to={`/us`}>US</Link></li> </ul> <form className="d-flex" role="search"> <input className="form-control me-2" type="search" placeholder="Search" aria-label="Search"/> <button className="btn btn-outline-success" type="submit">Search</button> </form> </div> </div> </nav> </> ) } export default Navbar;
问题原因
核心问题是News组件的key值重复。在App.js中,/india和/us的general分类路由使用了相同的key="general",React会认为这是同一个组件实例,从而复用现有组件,不会触发重新渲染和数据更新。同理,其他同分类不同国家的路由(如/india/entertainment和/us/entertainment)也共用了相同的key,导致切换时组件不更新。
解决方法
为每个News组件设置唯一的key值,结合country和category生成唯一标识,确保不同国家同分类的路由对应不同的key。
修改App.js中的Route配置,将key改为${country}-${category}的形式:
<Routes> <Route exact path="/" element={<Navigate to="/india" replace={true} />}/> <Route exact path="/india" element={<News key="in-general" category="general" country="in"/>}/> <Route exact path="/india/entertainment" element={<News key="in-entertainment" category="entertainment" country="in"/>}/> <Route exact path="/india/sports" element={<News key="in-sports" category="sports" country="in"/>}/> <Route exact path="/india/business" element={<News key="in-business" category="business" country="in"/>}/> <Route exact path="/india/health" element={<News key="in-health" category="health" country="in"/>}/> <Route exact path="/india/science" element={<News key="in-science" category="science" country="in"/>}/> <Route exact path="/india/technology" element={<News key="in-technology" category="technology" country="in"/>}/> <Route exact path="/us" element={<News key="us-general" category="general" country="us"/>}/> <Route exact path="/us/entertainment" element={<News key="us-entertainment" category="entertainment" country="us"/>}/> <Route exact path="/us/sports" element={<News key="us-sports" category="sports" country="us"/>}/> <Route exact path="/us/business" element={<News key="us-business" category="business" country="us"/>}/> <Route exact path="/us/health" element={<News key="us-health" category="health" country="us"/>}/> <Route exact path="/us/science" element={<News key="us-science" category="science" country="us"/>}/> <Route exact path="/us/technology" element={<News key="us-technology" category="technology" country="us"/>}/> </Routes>
这样修改后,每个路由对应的News组件key都是唯一的,React会在切换路由时销毁旧组件并创建新组件,从而触发数据更新。
额外优化(可选)
可以简化路由配置,使用动态路由减少重复代码:
<Routes> <Route exact path="/" element={<Navigate to="/india" replace={true} />}/> <Route path="/:country" element={<News category="general" />}/> <Route path="/:country/:category" element={<News />}/> </Routes>
然后在News组件中通过useParams获取country和category参数,并在组件内部监听参数变化来触发数据请求:
import { useParams, useEffect } from 'react-router-dom'; const News = () => { const { country, category = "general" } = useParams(); useEffect(() => { // 发起数据请求,更新页面内容 fetchNews(country, category); }, [country, category]); // 其他组件逻辑... }
这种方式更简洁,也能从根源上避免key重复的问题。
内容的提问来源于stack exchange,提问作者Dnyaneshwar Shinde
相关产品推荐
相关产品推荐

