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

