React Router报错:useLocation需在<Router>上下文,求组件卸载动画方案
路由切换动画实现与报错修复
核心报错原因
useLocation() 钩子必须在 <BrowserRouter> 组件的内部上下文调用,你的代码中在 <BrowserRouter> 外部就调用了该钩子,导致无法获取Router上下文,触发报错:"useLocation() may be used only in the context of a <Router> component?"
修复步骤
1. 调整组件结构,将useLocation移到Router内部
拆分App组件,创建内部子组件在<BrowserRouter>内部使用useLocation:
import { BrowserRouter, Routes, Route, useLocation, Navigate } from 'react-router-dom'; import { AnimatePresence } from 'framer-motion'; // 内部组件:在Router上下文内使用useLocation function AnimatedRoutes() { const location = useLocation(); return ( <AnimatePresence mode='wait'> <Routes key={location.pathname} location={location}> <Route path='/' element={<Portfolio />}> {/* 修正index路由冲突:访问/时默认跳转到home */} <Route index element={<Navigate to='home' />} /> <Route path='home' element={<Home />}/> <Route path='projects' element={<Projects />}/> <Route path='info' element={<Info />}/> <Route path='contact' element={<Contact />}/> </Route> </Routes> </AnimatePresence> ); } function App() { return ( <BrowserRouter> <AnimatedRoutes /> </BrowserRouter> ); } export default App;
2. 修复Portfolio组件的语法错误
你的Portfolio组件存在未闭合标签问题,需补充完整:
function Portfolio() { return ( <Container className='bg' maxWidth={false}> <Container className='cont' maxWidth={false}> <h1 className='header'>Milos Glamocak</h1> <nav className='navContainer'> <ul className='menu'> <li className='menuLine'><Link to='home' className='link'>Home</Link></li> <li className='menuLine'><Link to='projects' className='link'>Projects</Link></li> <li className='menuLine'><Link to='info' className='link'>Info</Link></li> <li className='menuLine'><Link to='contact' className='link'>Contact</Link></li> </ul> <Outlet /> </nav> </Container> {/* 此处补充剩余组件内容 */} </Container> ) }
3. 路由规则修正说明
原代码中根路由下的index路由同时设置path='home'会导致匹配冲突:
- 若希望访问
/时自动跳转到/home,用<Navigate>组件实现重定向 - 若直接通过
/home访问页面,移除index属性,保留path='home'即可
动画生效补充
确保子组件(Home/Projects等)添加Framer Motion的动画属性,示例:
import { motion } from 'framer-motion'; function Home() { return ( <motion.div initial={{ opacity: 0, x: -20 }} animate={{ opacity: 1, x: 0 }} exit={{ opacity: 0, x: 20 }} transition={{ duration: 0.3 }} > {/* 组件内容 */} </motion.div> ); }
内容的提问来源于stack exchange,提问作者Milos Glamocak
相关产品推荐
相关产品推荐

