React谷歌登录成功后页面重定向失败问题求助
我正在给网站实现谷歌登录按钮,登录成功后想重定向到首页。目前能正常登录并获取用户信息,但重定向环节出问题了。尝试用useNavigate钩子时,明明已经用<Router>包裹,却一直收到**useNavigate() may be used only in the context of a
现有代码
App.js
import { Component } from "react"; import "./App.css"; import { GoogleLogin } from '@react-oauth/google'; import {BrowserRouter as Router, Route, Routes, useNavigate} from 'react-router-dom'; import { useState } from 'react'; import Home from './pages/Home'; import Locations from './pages/Locations'; import Login from './pages/Login'; import ViewMeetings from './pages/ViewMeetings'; import BookMeeting from './pages/BookMeeting'; import YourMeetings from './pages/YourMeetings'; import NavBar from './components/NavBar' function App() { // Use this function to trigger the // "LogIn With Google" process // at the end of which the onSuccess function // is triggered const [isLoggedIn, setIsLoggedIn] = useState(false); const navigate = useNavigate(); return ( <Router> <div className="App"> {window.location.pathname === '/login' && ( <GoogleLogin onSuccess={credentialResponse => { console.log(credentialResponse); setIsLoggedIn(true); navigate('/home'); }} onError={() => { console.log('Login Failed'); }} /> )} <NavBar /> <Routes> <Route path="/" element={<Home />} /> <Route path="/locations" element={<Locations />} /> <Route path="/login" element={<Login setIsLoggedIn={setIsLoggedIn}/>} /> <Route path="/view-meetings" element={<ViewMeetings />} /> <Route path="/book-meeting" element={<BookMeeting />} /> <Route path="/your-meetings" element={<YourMeetings />} /> </Routes> </div> </Router> ); } export default App;
Home.js
import React from 'react'; function Home() { return ( <div className='homepage'> <h1>You are now logged in</h1> </div> ) } export default Home;
index.js
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import { GoogleOAuthProvider } from '@react-oauth/google'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <GoogleOAuthProvider clientId="xxx"> <App /> </GoogleOAuthProvider> </React.StrictMode> ); reportWebVitals();
问题原因及解决方案
问题根源
useNavigate必须在<Router>提供的上下文环境中调用,但你在App组件的顶层直接调用了useNavigate,而<Router>是在App组件的return里渲染的——此时App组件本身并不在Router的上下文里,所以钩子报错。
解决方案1:将登录逻辑移到Login页面(推荐)
把GoogleLogin组件放到Login页面内,Login组件属于路由配置中的页面,自然处于Router上下文,可正常使用useNavigate。
修改后的App.js
import { useState } from 'react'; import "./App.css"; import {BrowserRouter as Router, Route, Routes} from 'react-router-dom'; import Home from './pages/Home'; import Locations from './pages/Locations'; import Login from './pages/Login'; import ViewMeetings from './pages/ViewMeetings'; import BookMeeting from './pages/BookMeeting'; import YourMeetings from './pages/YourMeetings'; import NavBar from './components/NavBar' function App() { const [isLoggedIn, setIsLoggedIn] = useState(false); return ( <Router> <div className="App"> <NavBar /> <Routes> <Route path="/" element={<Home />} /> <Route path="/locations" element={<Locations />} /> <Route path="/login" element={<Login setIsLoggedIn={setIsLoggedIn}/>} /> <Route path="/view-meetings" element={<ViewMeetings />} /> <Route path="/book-meeting" element={<BookMeeting />} /> <Route path="/your-meetings" element={<YourMeetings />} /> </Routes> </div> </Router> ); } export default App;
修改后的Login.js
import React from 'react'; import { GoogleLogin } from '@react-oauth/google'; import { useNavigate } from 'react-router-dom'; function Login({ setIsLoggedIn }) { const navigate = useNavigate(); return ( <div> <GoogleLogin onSuccess={credentialResponse => { console.log(credentialResponse); setIsLoggedIn(true); navigate('/'); // 对应首页路由,也可以改成'/home' }} onError={() => { console.log('Login Failed'); }} /> </div> ) } export default Login;
解决方案2:在App内创建Router上下文内的子组件
如果一定要在App组件里处理登录逻辑,可以把内容部分抽成一个内部组件,让它处于Router上下文里:
function App() { const [isLoggedIn, setIsLoggedIn] = useState(false); // 内部组件,处于Router上下文 const AppContent = () => { const navigate = useNavigate(); return ( <div className="App"> {window.location.pathname === '/login' && ( <GoogleLogin onSuccess={credentialResponse => { console.log(credentialResponse); setIsLoggedIn(true); navigate('/home'); }} onError={() => { console.log('Login Failed'); }} /> )} <NavBar /> <Routes> <Route path="/" element={<Home />} /> <Route path="/locations" element={<Locations />} /> <Route path="/login" element={<Login setIsLoggedIn={setIsLoggedIn}/>} /> <Route path="/view-meetings" element={<ViewMeetings />} /> <Route path="/book-meeting" element={<BookMeeting />} /> <Route path="/your-meetings" element={<YourMeetings />} /> </Routes> </div> ) } return ( <Router> <AppContent /> </Router> ); }
内容的提问来源于stack exchange,提问作者Hong
相关产品推荐
相关产品推荐

