You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 14:58:13