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

React Native中自定义Hook结合Redux实现Google登录的问题

解决方案:将自定义Google登录Hook与Redux结合

核心思路是遵守Hook的调用规则(仅在函数组件/自定义Hook中调用),把Google登录的UI交互逻辑留在Hook里,登录结果通过回调传递给组件,再由组件触发Redux的action更新状态。以下是具体实现步骤:

1. 调整自定义Google登录Hook

添加onSuccess回调参数,用于在登录成功后将token传递给外部组件,进而触发Redux action:

import * as Google from 'expo-auth-session/providers/google';
import { useEffect, useState } from 'react';

const useGoogleSignIn = ({ onSuccess }) => {
  const useProxy = __DEV__ ? true : false;
  const [request, response, promptAsync] = Google.useAuthRequest({
    androidClientId: '',
    iosClientId: '',
    expoClientId: '',
  });
  const [accessToken, setAccessToken] = useState();

  useEffect(() => {
    if (response?.type === 'success') {
      const token = response.authentication.accessToken;
      setAccessToken(token);
      // 触发成功回调,将token传递给组件
      onSuccess?.(token);
    }
  }, [response, onSuccess]);

  const promptMobileGoogleSignIn = () => promptAsync({ useProxy, showInRecents: true });
  const isGoogleClientAvailable = !!request;

  return {
    response,
    accessToken,
    isGoogleClientAvailable,
    promptMobileGoogleSignIn,
  };
};

export default useGoogleSignIn;

2. 完善Redux Action

拆分action职责,分别处理登录成功、失败和初始化检查token的逻辑:

import AsyncStorage from '@react-native-async-storage/async-storage';
import { GOOGLE_LOGIN_SUCCESS, GOOGLE_LOGIN_FAIL, GOOGLE_LOGIN_INIT } from './types';

// 登录成功:存储token并更新Redux状态
export const googleLoginSuccess = (token) => async (dispatch) => {
  await AsyncStorage.setItem('google_token', token);
  dispatch({ type: GOOGLE_LOGIN_SUCCESS, payload: token });
};

// 登录失败:更新Redux状态
export const googleLoginFail = () => ({
  type: GOOGLE_LOGIN_FAIL,
});

// 初始化检查:启动App时读取本地存储的token,自动登录
export const checkStoredToken = () => async (dispatch) => {
  try {
    const token = await AsyncStorage.getItem('google_token');
    if (token) {
      dispatch({ type: GOOGLE_LOGIN_SUCCESS, payload: token });
    } else {
      dispatch({ type: GOOGLE_LOGIN_INIT });
    }
  } catch (error) {
    dispatch(googleLoginFail());
  }
};

3. 在组件中整合Hook与Redux

在登录组件中调用自定义Hook,同时通过Redux的useDispatch触发状态更新:

import React, { useEffect } from 'react';
import { View, Button } from 'react-native';
import { useDispatch } from 'react-redux';
import useGoogleSignIn from '../hooks/useGoogleSignIn';
import { googleLoginSuccess, googleLoginFail } from '../redux/actions/authActions';

const LoginScreen = () => {
  const dispatch = useDispatch();
  const { 
    isGoogleClientAvailable, 
    promptMobileGoogleSignIn,
    response
  } = useGoogleSignIn({
    onSuccess: (token) => {
      // 登录成功后触发Redux action
      dispatch(googleLoginSuccess(token));
    }
  });

  // 处理登录取消或错误的情况
  useEffect(() => {
    if (response?.type === 'cancel' || response?.type === 'error') {
      dispatch(googleLoginFail());
    }
  }, [response, dispatch]);

  return (
    <View>
      {isGoogleClientAvailable && (
        <Button 
          title="Sign in with Google" 
          onPress={promptMobileGoogleSignIn} 
        />
      )}
    </View>
  );
};

export default LoginScreen;

4. App启动时自动检查token

在根组件中调用初始化action,读取本地存储的token实现自动登录:

import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { checkStoredToken } from './redux/actions/authActions';
import LoginScreen from './screens/LoginScreen';
import HomeScreen from './screens/HomeScreen';

const App = () => {
  const dispatch = useDispatch();
  const { isAuthenticated } = useSelector(state => state.auth);

  useEffect(() => {
    dispatch(checkStoredToken());
  }, [dispatch]);

  return isAuthenticated ? <HomeScreen /> : <LoginScreen />;
};

export default App;

关键说明

  • 自定义Hook专注处理Google登录的认证流程和UI交互,不直接操作Redux,符合单一职责原则
  • 组件作为中间层,连接Hook和Redux,既遵守Hook的调用规则,又实现状态的全局管理
  • Redux action仅负责状态更新和本地存储操作,保持逻辑纯净

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 20:18:23