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

React谷歌登录成功后页面重定向失败问题求助

谷歌登录成功后重定向失败:useNavigate钩子报错

我正在给网站实现谷歌登录按钮,登录成功后想重定向到首页。目前能正常登录并获取用户信息,但重定向环节出问题了。尝试用useNavigate钩子时,明明已经用<Router>包裹,却一直收到**useNavigate() may be used only in the context of a component.**错误。

现有代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 08:58:14