如何在Expo/react-native类组件中实现Google Authentication功能
React Native Expo 类组件集成Google认证解决方案
方案1:通过高阶组件(HOC)适配Hook(推荐,改动最小)
React Hook仅支持在函数组件或自定义Hook中调用,我们可以通过一个简单的高阶组件将useAuthRequest返回的认证相关参数作为props注入类组件,复用官方的封装逻辑。
import * as React from 'react'; import * as WebBrowser from 'expo-web-browser'; import * as Google from 'expo-auth-session/providers/google'; import { Button, Component } from 'react-native'; WebBrowser.maybeCompleteAuthSession(); // 高阶组件:注入Google认证相关参数 const withGoogleAuth = (WrappedComponent) => { return (props) => { const [request, response, promptAsync] = Google.useAuthRequest({ expoClientId: 'GOOGLE_GUID.apps.googleusercontent.com', iosClientId: 'GOOGLE_GUID.apps.googleusercontent.com', androidClientId: 'GOOGLE_GUID.apps.googleusercontent.com', webClientId: 'GOOGLE_GUID.apps.googleusercontent.com', }); return <WrappedComponent {...props} googleAuth={{request, response, promptAsync}} /> } } class App extends Component { // 替代函数组件中的useEffect监听响应变化 componentDidUpdate(prevProps) { const currentResponse = this.props.googleAuth.response; if (currentResponse && currentResponse !== prevProps.googleAuth.response) { if (currentResponse.type === 'success') { const { authentication } = currentResponse; // 此处写认证成功后的业务逻辑,如存储token、跳转页面等 console.log('认证成功', authentication); } } } render() { const { request, promptAsync } = this.props.googleAuth; return ( <Button disabled={!request} title="Login" onPress={() => promptAsync()} /> ); } } // 导出被高阶组件包裹后的类组件 export default withGoogleAuth(App);
方案2:直接调用底层API实现(无需Hook适配)
如果不想引入高阶组件,也可以直接使用expo-auth-session的底层方法手动实现完整认证流程:
import * as React from 'react'; import * as WebBrowser from 'expo-web-browser'; import * as AuthSession from 'expo-auth-session'; import * as Google from 'expo-auth-session/providers/google'; import { Button, Component } from 'react-native'; WebBrowser.maybeCompleteAuthSession(); export default class App extends Component { state = { request: null, promptAsync: null } async componentDidMount() { // 初始化Google认证配置 const config = { expoClientId: 'GOOGLE_GUID.apps.googleusercontent.com', iosClientId: 'GOOGLE_GUID.apps.googleusercontent.com', androidClientId: 'GOOGLE_GUID.apps.googleusercontent.com', webClientId: 'GOOGLE_GUID.apps.googleusercontent.com', }; // 手动构建认证请求 const discovery = await AuthSession.fetchDiscoveryAsync("https://accounts.google.com"); const clientId = Google.getPlatformClientId(config); const request = new AuthSession.AuthRequest({ clientId, scopes: config.scopes ?? ['openid', 'https://www.googleapis.com/auth/userinfo.profile', 'https://www.googleapis.com/auth/userinfo.email'], redirectUri: config.redirectUri ?? AuthSession.makeRedirectUri({ useProxy: config.useProxy, native: config.nativeClientId }), extraParams: config.hostedDomain ? { hd: config.hostedDomain } : {}, usePKCE: true, }); const promptAsync = (options) => request.promptAsync(discovery, options); this.setState({ request, promptAsync }); } componentDidUpdate(prevProps, prevState) { const currentResponse = this.state.request?.response; if (currentResponse && currentResponse !== prevState.request?.response) { if (currentResponse.type === 'success') { const { authentication } = currentResponse; // 此处写认证成功后的业务逻辑 console.log('认证成功', authentication); } } } render() { const { request, promptAsync } = this.state; return ( <Button disabled={!request} title="Login" onPress={() => promptAsync?.()} /> ); } }
注意事项
- 请将代码中各类ClientId替换为你在Google Cloud后台申请的对应平台实际值
- 安卓、iOS端需要提前配置好应用包名、签名等信息,否则会触发认证报错
内容的提问来源于stack exchange,提问作者Connor Torrell
相关产品推荐
相关产品推荐

