在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
相关产品推荐
相关产品推荐

