React Router V6修改URL路径触发应用重载,求原因
问题描述
用Create React App创建的应用,基于React Router Dom v6和Redux Toolkit开发。正常通过NavLink导航时页面无刷新,但在浏览器地址栏直接输入指定路径(如/starred)或刷新当前页面时,整个应用会重载,导致Redux状态被重置。临时改用Hash Router后,输入当前页面的相同URL仍会触发重载。
相关代码
Index.js
const container = document.getElementById('root'); const root = createRoot(container); const router = createBrowserRouter( createRoutesFromElements( <Route path='/' element={<App/>}> <Route index path='starred' element={<ArticleList/>}/> <Route index path='latest' element={<ArticleList/>}/> </Route> ) ) root.render( <Provider store={store}> <RouterProvider router={router}/> </Provider> );
App.js
function App() { const Outlet = useOutlet(); const theme = useSelector(state => state.theme.getTheme); return ( <div className='App' data-theme={theme}> <Header/> { Outlet ?? <ArticleList/>} <Footer/> </div> ); }
Header.js(使用NavLink实现无刷新导航)
export default function Header() { const activeStyle = { color: 'coral', }; const inactiveStyle = { 'fontSize':'small', } const matches = useMatches(); return ( <div className='header-nav'> <div> <NavLink to='/'> <i className="fa-brands fa-3x fa-hacker-news" ></i> </NavLink> </div> <div> <h1> Hacker News </h1> </div> <div className='header-space'> <span> <NavLink style={({ isActive }) => matches.length === 1 || isActive ? activeStyle : inactiveStyle } to='latest' end>latest</NavLink> </span> | <span> <NavLink style={({ isActive }) => isActive ? activeStyle : inactiveStyle } to='starred'>starred</NavLink> </span> </div> <ToggleTheme/> </div> ) }
ArticleList.js
export default function ArticleList() { const { data: articleIds, } = useGetIdsQuery(); const [index, setIndex] = useState(0); const [starredIndex, setStarredIndex] = useState(0); const location = useMatches(); const starredIds = useSelector(articlesSelector.selectIds); const isStarred = location.find(({pathname}) => pathname === '/starred')?.pathname === '/starred'; const displayArticles = isStarred ? starredIds?.slice(starredIndex, starredIndex + 12) : articleIds?.slice(index, index + 12); const onClickHandler = () => { if(displayArticles.length < 12) return; if(isStarred) { const nextPage = starredIndex + 12; setStarredIndex(nextPage); } const nextPage = index + 12; setIndex(nextPage) } return ( <div> <ol className="list-groupMine"> {displayArticles?.map((id)=><Article key={id} id={id}/>)} </ol> <div className='show-more'> <button className='showMoreButton' onClick={onClickHandler}> show more </button> </div> </div> ) }
Article.js
export default function Article({id}){ const { data } = useGetArticleQuery(id ?? skipToken); const { url, title, score, kids, by } = data?.entities[id] ?? {}; const domain = url ? new URL(url) : undefined; const dispatch = useDispatch(); const selectEntities = useSelector(articlesSelector.selectEntities); const isSaved = selectEntities[id]?.saved === 'saved' ? 'saved' : 'save'; const onClickHandler = () => { if(selectEntities[id]) { return dispatch(removeSaved(id)); } dispatch(addSaved({...data?.entities[id], saved:'saved' })); } return( <div className="spacer"> <div> <span > <a href={url} style={{'fontFamily': 'monospace'}} target="_blank" rel="noopener noreferrer">{title}</a> </span> <span> <a className="extra-inline-style" href={url} style={{ 'color':'grey',}} target="_blank" rel="noopener noreferrer">{`(${domain?.host.replace('www.','') ?? ''})`}</a> </span> </div> <div className="subtext"> <p> {`${score} points by ${by} `} |{` ${kids?.length ?? 0} comments `} | {isSaved === 'saved'? <BsStarFill style={{'color': 'orange'}} onClick={onClickHandler}/> : <BsStar onClick={onClickHandler}/> } <span>{' ' + isSaved}</span> </p> </div> </div> ) }
内容的提问来源于stack exchange,提问作者Ale
相关产品推荐
相关产品推荐

