react-router-dom跳转异常:地址栏变化但页面需刷新才能生效
地址栏变化但页面不跳转的React路由问题
我正在开发一个React项目,点击链接时地址栏会变化,但页面不会自动跳转,必须手动刷新才能看到对应页面。以下是我的代码:
App组件代码
import Hero from './components/Hero' import { BrowserRouter, Route, Switch } from 'react-router-dom'; import ContactPage from './components/ContactPage'; import Solar from './components/Solar'; import Navbar from './components/Navbar'; import Wind from './components/Wind'; import Mission from './components/Mission' import Vision from './components/Vision' import Projects from './components/Projects'; function App() { return ( <BrowserRouter> <Navbar /> <Switch> <Route exact path='/' component={Hero} /> <Route path='/contact' component={ContactPage} /> <Route path='/solar' component={Solar} /> <Route path='/wind' component={Wind} /> <Route path='/mission' component={Mission} /> <Route path='/vision' component={Vision} /> <Route path='/projects' component={Projects} /> </Switch> </BrowserRouter> ); } export default App;
Navbar组件代码
import React, { useEffect, useState } from 'react' import { AiOutlineMenu, AiOutlineClose, AiOutlineDown } from 'react-icons/ai' import { motion } from 'framer-motion' import { useOnHoverOutside } from '../hooks/useOnHoverOutside' import { Link } from 'react-router-dom' const Navbar = () => { const [nav, setNav] = useState(false) const [color, setColor] = useState('transparent') const [textColor, setTextColor] = useState('white') const [isAboutUsMenuDropdown, setIsAboutUsMenuDropDown] = useState(false) const [isProjectsMenuDropdown, setIsProjectsMenuDropDown] = useState(false) const handleNav = () => { setNav(!nav); } const closeHoverMenu = () => { setIsAboutUsMenuDropDown(false); setIsProjectsMenuDropDown(false) } useOnHoverOutside(closeHoverMenu) // Call the hook useEffect(() => { const changeColor = () => { if (window.scrollY >= 90) { setColor('#ffffff') setTextColor('#006400') } else { setColor('transparent') setTextColor('#ffffff') } } window.addEventListener('scroll', changeColor) }, []) return ( <motion.nav animate={{ backgroundColor: `${color}` }} initial={{ backgroundColor: 'transparent' }} className='fixed left-0 top-0 w-full z-10 ease-in duration-300' > <div className='max-w-[1240px] m-auto flex justify-between items-center p-4 text-white'> <a to="/"> <img src={require("../images/calogo.png")} className="w-20 h-20" alt="/" /> </a> <ul style={{ color: `${textColor}` }} className='hidden sm:flex font-semibold' > <li className='p-4' onMouseOver={() => setIsAboutUsMenuDropDown(true)} onMouseOut={() => setIsAboutUsMenuDropDown(false)}> <a href='/' className='inline-flex'>About Us <AiOutlineDown className='ml-2 mt-1' /></a> {isAboutUsMenuDropdown && ( <ul className="absolute z-10 bg-gray-600/60 text-white rounded py-2 mt-2" style={{ animation: "slideDown 0.3s ease-out forwards" }}> <li className="py-1"> <Link to="/mission" className="block px-4 py-1 text-white hover:bg-gray-500"> Mission </Link> </li> <li className="py-1"> <Link to="/vision" className="block px-4 py-1 text-white hover:bg-gray-500"> Vision </Link> </li> </ul> )} </li> <li className='p-4' onMouseOver={() => setIsProjectsMenuDropDown(true)} onMouseOut={() => setIsProjectsMenuDropDown(false)}> <Link to='/projects' className='inline-flex'>Projects <AiOutlineDown className='ml-2 mt-1' /></Link> {isProjectsMenuDropdown && ( <ul className="absolute z-10 bg-gray-600/60 text-white rounded py-2 mt-2"> <li className="py-1"> <Link to="/solar" className="block px-4 py-1 text-white hover:bg-gray-500"> Solar </Link> </li> <li className="py-1"> <Link to="/wind" className="block px-4 py-1 text-white hover:bg-gray-500"> Wind </Link> </li> </ul> )} </li> <li className='p-4'> <Link to='/contact'>Contact</Link> </li> </ul> {/* Mobile Button */} <div onClick={handleNav} className='block sm:hidden z-10'> {nav ? ( <AiOutlineClose size={20} style={{ color: `${textColor}` }} /> ) : ( <AiOutlineMenu size={20} style={{ color: `${textColor}` }} /> )} </div> {/* Mobile Menu */} <div className={nav ? 'sm:hidden absolute top-0 left-0 right-0 bottom-0 flex justify-center items-center w-full h-screen bg-black text-center ease-in duration-300' : 'sm:hidden absolute top-0 left-[-100%] right-0 bottom-0 flex justify-center items-center w-full h-screen bg-black text-center ease-in duration-300'} > <ul> <li className='p-4 text-4xl hover:text-gray-500'> <a href='/#aboutus'>About Us</a> </li> <li className='p-4 text-4xl hover:text-gray-500'> <a href='/#mission'>Mission</a> </li> <li className='p-4 text-4xl hover:text-gray-500'> <a href='/#vision'>Vision</a> </li> <li className='p-4 text-4xl hover:text-gray-500'> <a href='/#projects'>Projects</a> </li> <li className='p-4 text-4xl hover:text-gray-500'> <a href='/#solar'>Solar</a> </li> <li className='p-4 text-4xl hover:text-gray-500'> <a href='/#wind'>Wind</a> </li> <li className='p-4 text-4xl hover:text-gray-500'> <a href='/#contact'>Contact</a> </li> </ul> </div> </div> </motion.nav> ) } export default Navbar
问题原因及解决方案
问题出在混用了原生HTML的<a>标签和React Router的<Link>组件,原生<a>标签会触发浏览器默认跳转行为,导致页面路由异常(地址栏变化但组件不更新),而React Router需要用<Link>实现无刷新的客户端路由。
需要修改的几个地方:
- Logo链接:
<a>标签不支持to属性,替换为<Link>组件:
<Link to="/"> <img src={require("../images/calogo.png")} className="w-20 h-20" alt="logo" /> </Link>
- About Us主链接:将原生
<a href='/'>替换为<Link to='/'>:
<Link to='/' className='inline-flex'>About Us <AiOutlineDown className='ml-2 mt-1' /></Link>
- 移动端菜单所有链接:全部替换为
<Link>组件,同时去掉路径中的#(#是锚点链接,不是路由路径):
<ul> <li className='p-4 text-4xl hover:text-gray-500'> <Link to='/'>About Us</Link> </li> <li className='p-4 text-4xl hover:text-gray-500'> <Link to='/mission'>Mission</Link> </li> <li className='p-4 text-4xl hover:text-gray-500'> <Link to='/vision'>Vision</Link> </li> <li className='p-4 text-4xl hover:text-gray-500'> <Link to='/projects'>Projects</Link> </li> <li className='p-4 text-4xl hover:text-gray-500'> <Link to='/solar'>Solar</Link> </li> <li className='p-4 text-4xl hover:text-gray-500'> <Link to='/wind'>Wind</Link> </li> <li className='p-4 text-4xl hover:text-gray-500'> <Link to='/contact'>Contact</Link> </li> </ul>
- 检查
useOnHoverOutside钩子:确保该钩子没有错误拦截<Link>的点击事件,如果钩子绑定的元素包含<Link>,需调整目标元素范围,避免干扰路由跳转。
总结
将所有路由跳转链接替换为React Router的<Link>组件,即可解决地址栏变化但页面不更新的问题。<Link>会拦截浏览器默认跳转行为,通过React Router的客户端路由机制更新组件,无需手动刷新页面。
内容的提问来源于stack exchange,提问作者Egemen Özyürek
相关产品推荐
相关产品推荐

