React项目中useNavigate()报错:需在<Router>上下文使用的问题求助
报错信息
Uncaught runtime errors: × ERROR useNavigate() may be used only in the context of a <Router> component. at invariant (http://localhost:3000/static/js/bundle.js:1123:11) at useNavigateUnstable (http://localhost:3000/static/js/bundle.js:66522:102) at useNavigate (http://localhost:3000/static/js/bundle.js:66519:46) at App (http://localhost:3000/static/js/bundle.js:83:81) at renderWithHooks (http://localhost:3000/static/js/bundle.js:26618:22) at mountIndeterminateComponent (http://localhost:3000/static/js/bundle.js:29904:17) at beginWork (http://localhost:3000/static/js/bundle.js:31200:20) at HTMLUnknownElement.callCallback (http://localhost:3000/static/js/bundle.js:16210:18) at Object.invokeGuardedCallbackDev (http://localhost:3000/static/js/bundle.js:16254:20) at invokeGuardedCallback (http://localhost:3000/static/js/bundle.js:16311:35) ERROR useNavigate() may be used only in the context of a <Router> component. at invariant (http://localhost:3000/static/js/bundle.js:1123:11) at useNavigateUnstable (http://localhost:3000/static/js/bundle.js:66522:102) at useNavigate (http://localhost:3000/static/js/bundle.js:66519:46) at App (http://localhost:3000/static/js/bundle.js:83:81) at renderWithHooks (http://localhost:3000/static/js/bundle.js:26618:22) at mountIndeterminateComponent (http://localhost:3000/static/js/bundle.js:29904:17) at beginWork (http://localhost:3000/static/js/bundle.js:31200:20) at HTMLUnknownElement.callCallback (http://localhost:3000/static/js/bundle.js:16210:18) at Object.invokeGuardedCallbackDev (http://localhost:3000/static/js/bundle.js:16254:20) at invokeGuardedCallback (http://localhost:3000/static/js/bundle.js:16311:35) ERROR useNavigate() may be used only in the context of a <Router> component. at invariant (http://localhost:3000/static/js/bundle.js:1123:11) at useNavigateUnstable (http://localhost:3000/static/js/bundle.js:66522:102) at useNavigate (http://localhost:3000/static/js/bundle.js:66519:46) at App (http://localhost:3000/static/js/bundle.js:83:81) at renderWithHooks (http://localhost:3000/static/js/bundle.js:26618:22) at mountIndeterminateComponent (http://localhost:3000/static/js/bundle.js:29904:17) at beginWork (http://localhost:3000/static/js/bundle.js:31200:20) at beginWork$1 (http://localhost:3000/static/js/bundle.js:36163:18) at performUnitOfWork (http://localhost:3000/static/js/bundle.js:35432:16) at workLoopSync (http://localhost:3000/static/js/bundle.js:35355:9)
问题代码
App.js
import logo from './logo.svg'; import './App.css'; import LoginForm from './components/LoginForm'; import SignUp from './signup'; import { BrowserRouter as Router, Routes, Route, Link, useNavigate } from 'react-router-dom'; function App() { const navigate = useNavigate(); const handleSignUpClick = () => { navigate('/signup'); } return ( <Router> <div className="Login"> <h3> <a className="nav-link active" aria-current="page" href="#" onClick={handleSignUpClick}> Sign up </a> </h3> <Routes> <Route path="/" element={<LoginForm />} /> <Route path="/signup" element={<SignUp />} /> </Routes> </div> </Router> ); } export default App;
LoginForm.js
import React, { useState } from 'react'; import { Button, Form, FormGroup, Label, Input, InputGroup } from 'reactstrap'; import { FaEye, FaEyeSlash } from 'react-icons/fa'; function LoginForm() { const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [showPassword, setShowPassword] = useState(false); const handleSubmit = (event) => { //handle submit } const toggleShowPassword = () => { setShowPassword(!showPassword); } return ( <div className="form-box"> <Form onSubmit={handleSubmit}> <FormGroup> <Label for="username">Username</Label> <Input type="text" name="username" id="username" value={username} onChange={e => setUsername(e.target.value)} /> </FormGroup> <FormGroup> <Label for="password">Password</Label> <InputGroup> <Input type={showPassword ? 'text' : 'password'} name="password" id="password" value={password} onChange={e => setPassword(e.target.value)} /> <Button onClick={toggleShowPassword}> {showPassword ? <FaEyeSlash /> : <FaEye />} </Button> </InputGroup> </FormGroup> <div className="text-center"> <Button>Submit</Button> </div> </Form> </div> ); } export default LoginForm;
SignUp.js
import './App.css'; function SignUp() { return ( <div className="Login"> <h1>Application</h1> </div> ); } export default SignUp;
问题原因
你在App组件中直接调用了useNavigate(),但App组件是<Router>的父组件,此时useNavigate还未进入Router的上下文环境,所以触发了错误。
修复方案
方式一:用Link组件替代手动跳转(推荐)
React Router提供的<Link>组件是专门做路由跳转的,无需手动调用useNavigate,直接替换原有的<a>标签即可:
<Link className="nav-link active" aria-current="page" to="/signup"> Sign up </Link>
同时可以删掉useNavigate的导入和handleSignUpClick函数,代码更简洁。
方式二:将useNavigate移到Router内部组件中
如果一定要用useNavigate,可以把跳转逻辑抽成独立组件,这个组件必须放在<Router>内部:
// 新建跳转组件 function SignUpLink() { const navigate = useNavigate(); const handleSignUpClick = () => { navigate('/signup'); }; return ( <a className="nav-link active" aria-current="page" href="#" onClick={handleSignUpClick}> Sign up </a> ); } // 在App的Router内部使用该组件 function App() { return ( <Router> <div className="Login"> <h3> <SignUpLink /> </h3> <Routes> <Route path="/" element={<LoginForm />} /> <Route path="/signup" element={<SignUp />} /> </Routes> </div> </Router> ); }
完整修复后的App.js
import logo from './logo.svg'; import './App.css'; import LoginForm from './components/LoginForm'; import SignUp from './signup'; import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom'; function App() { return ( <Router> <div className="Login"> <h3> <Link className="nav-link active" aria-current="page" to="/signup"> Sign up </Link> </h3> <Routes> <Route path="/" element={<LoginForm />} /> <Route path="/signup" element={<SignUp />} /> </Routes> </div> </Router> ); } export default App;
内容的提问来源于stack exchange,提问作者Prasad B
相关产品推荐
相关产品推荐

