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

在React+Firebase应用中调用Google Calendar API的认证与访问问题

在React+Firebase应用中从Calendar.js访问Google Calendar API

既然你已经在App.js里完成了谷歌身份认证,接下来核心就是把认证后的凭据传递给Calendar.js组件,再用它调用Google Calendar API。下面是两种实用的实现方案:

方案一:通过Props传递认证凭据(适合组件层级较浅的场景)

先补全你App.js里的认证逻辑(假设用Firebase谷歌登录弹窗),再把googleAuth作为props传给Calendar组件:

完善后的App.js代码

import React from 'react'
import firebase from 'firebase'
import './App.css'
import AppBody from '../AppBody'
import AppHeader from '../AppHeader'
import Calendar from './Calendar' // 引入Calendar组件

class App extends React.Component {
  constructor() {
    super()
    this.state = {
      user: null,
      googleAuth: null
    }
  }

  componentDidMount() {
    // 初始化Firebase(如果还没做的话)
    const firebaseConfig = {
      // 替换成你的Firebase配置
    };
    if (!firebase.apps.length) {
      firebase.initializeApp(firebaseConfig);
    }

    // 监听用户登录状态变化
    firebase.auth().onAuthStateChanged(async (user) => {
      if (user) {
        // 获取Google认证的访问令牌
        const googleAuth = await user.getIdTokenResult();
        this.setState({ user, googleAuth });
      } else {
        this.setState({ user: null, googleAuth: null });
      }
    });
  }

  // 谷歌登录方法(可绑定到头部登录按钮)
  signInWithGoogle = () => {
    const provider = new firebase.auth.GoogleAuthProvider();
    // 添加Calendar API访问权限(按需选择readonly或全权限)
    provider.addScope('https://www.googleapis.com/auth/calendar.readonly');
    firebase.auth().signInWithPopup(provider);
  }

  render() {
    const { user, googleAuth } = this.state;
    return (
      <div className="App">
        <AppHeader user={user} onSignIn={this.signInWithGoogle} />
        <AppBody>
          {/* 将认证凭据传递给Calendar组件 */}
          <Calendar googleAuth={googleAuth} />
        </AppBody>
      </div>
    );
  }
}

export default App;

Calendar.js中调用API的实现

import React, { useEffect, useState } from 'react';

const Calendar = ({ googleAuth }) => {
  const [events, setEvents] = useState([]);

  useEffect(() => {
    // 只有拿到认证凭据才执行API调用
    if (!googleAuth) return;

    const initAndFetchEvents = async () => {
      // 加载Google API客户端
      await window.gapi.load('client', async () => {
        await window.gapi.client.init({
          apiKey: '你的Google API密钥',
          access_token: googleAuth.token, // 从Firebase获取的访问令牌
          discoveryDocs: ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"],
        });

        // 调用Calendar API获取用户日历事件
        const response = await window.gapi.client.calendar.events.list({
          calendarId: 'primary',
          timeMin: new Date().toISOString(),
          showDeleted: false,
          singleEvents: true,
          maxResults: 10,
          orderBy: 'startTime',
        });

        setEvents(response.result.items);
      });
    };

    initAndFetchEvents();
  }, [googleAuth]);

  return (
    <div className="Calendar">
      <h2>我的日历事件</h2>
      {events.length > 0 ? (
        <ul>
          {events.map(event => (
            <li key={event.id}>
              <h3>{event.summary}</h3>
              <p>{new Date(event.start.dateTime || event.start.date).toLocaleString()}</p>
            </li>
          ))}
        </ul>
      ) : (
        <p>{googleAuth ? '加载日历事件中...' : '请先登录'}</p>
      )}
    </div>
  );
};

export default Calendar;

方案二:使用React Context(适合组件层级较深的场景)

如果Calendar组件嵌套在多层组件下,逐层传props会很繁琐,用React Context共享认证状态更高效:

1. 创建AuthContext.js

import React, { createContext, useContext } from 'react';

const AuthContext = createContext();

export const AuthProvider = ({ children, value }) => {
  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};

export const useAuth = () => {
  return useContext(AuthContext);
};

2. 在App.js中包裹AuthProvider

// ... 其他导入
import { AuthProvider } from './AuthContext';

class App extends React.Component {
  // ... 之前的构造函数、componentDidMount逻辑不变

  render() {
    const { user, googleAuth } = this.state;
    return (
      <AuthProvider value={{ user, googleAuth, signInWithGoogle: this.signInWithGoogle }}>
        <div className="App">
          <AppHeader />
          <AppBody>
            <Calendar />
          </AppBody>
        </div>
      </AuthProvider>
    );
  }
}

3. Calendar.js中通过钩子获取凭据

import React, { useEffect, useState } from 'react';
import { useAuth } from './AuthContext';

const Calendar = () => {
  const { googleAuth } = useAuth();
  const [events, setEvents] = useState([]);

  // API调用逻辑和方案一完全一致
  useEffect(() => {
    if (!googleAuth) return;

    const initAndFetchEvents = async () => {
      await window.gapi.load('client', async () => {
        await window.gapi.client.init({
          apiKey: '你的Google API密钥',
          access_token: googleAuth.token,
          discoveryDocs: ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"],
        });

        const response = await window.gapi.client.calendar.events.list({
          calendarId: 'primary',
          timeMin: new Date().toISOString(),
          showDeleted: false,
          singleEvents: true,
          maxResults: 10,
          orderBy: 'startTime',
        });

        setEvents(response.result.items);
      });
    };

    initAndFetchEvents();
  }, [googleAuth]);

  // 渲染逻辑和方案一一致
  return (
    <div className="Calendar">
      <h2>我的日历事件</h2>
      {events.length > 0 ? (
        <ul>
          {events.map(event => (
            <li key={event.id}>
              <h3>{event.summary}</h3>
              <p>{new Date(event.start.dateTime || event.start.date).toLocaleString()}</p>
            </li>
          ))}
        </ul>
      ) : (
        <p>{googleAuth ? '加载日历事件中...' : '请先登录'}</p>
      )}
    </div>
  );
};

export default Calendar;

注意事项

  • 确保已在Google Cloud Console启用Google Calendar API,并配置好与Firebase一致的OAuth 2.0客户端ID。
  • 登录时添加的权限要匹配你的业务需求(比如calendar.readonly仅只读,calendar是全权限)。
  • 记得替换代码中的占位符(如Google API密钥、Firebase配置)为你自己的信息。

内容的提问来源于stack exchange,提问作者artooras

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:28:15