React Native登录鉴权条件判断异常:点击需两次才跳转
React Native登录鉴权跳转二次点击问题解决方案
问题背景
在React Native中实现用户登录鉴权逻辑:从后端获取token并存入SecureStore,点击图标时根据token是否存在跳转至注册/登录页或个人资料页。目前SecureStore中的token值能正确更新,但点击跳转时需第二次点击才能导航至对应页面,尝试过useEffect但认为其仅在组件渲染时更新值,无法解决点击时的问题。
现有代码
MusicScreen跳转逻辑
const MusicScreen = () => { //Constante de navegación const navigation = useNavigation(); //Estado para sacar el token de asyncStorage const [token, setToken] = useState(null); //Saca el token y lo almacena temporalmente en setToken const getToken = async () => { try { const storedToken = await SecureStore.getItemAsync('token'); setToken(storedToken); console.log(storedToken) } catch (error) { console.error('Error al obtener el token:', error); } }; const handleIconPress = () => { getToken(); if (token === null) { navigation.navigate('Register'); } else { navigation.navigate('Profile'); } }; return ( <View > <LinearGradient colors={['#c501e2','#fe0ab7','#ae3dff','transparent']} style={styles.Background}> <TouchableOpacity onPress={handleIconPress} style={styles.touchable}> <Image source={require('../files-logos/D-Corchea.png')} style={styles.image}/> </TouchableOpacity> </LinearGradient> </View> )};
ProfileScreen登出逻辑
const logout = async() => { try{ await SecureStore.deleteItemAsync('token'); const storedToken = await SecureStore.getItemAsync('token'); console.log(storedToken); }catch(e){ console.log('Error trying to delete de token:', e); } } const ProfileScreen= () => { const navigation = useNavigation(); return ( <View> <Background1/> <Text style={{fontWeight:'bold',}}>THis is the profile screen</Text> <Button title='logout' onPress={()=>{ logout(); navigation.navigate('Register'); }} /> </View> )}; export default ProfileScreen;
问题原因
handleIconPress中调用的getToken是异步函数,而setToken更新React状态属于异步操作。第一次点击时,getToken还未完成SecureStore的读取操作,token状态仍为旧值,导致判断逻辑基于旧值执行;第二次点击时状态已更新,判断才会生效。
解决方案
无需依赖组件状态token执行跳转判断,直接在异步读取流程中拿到最新token后立即处理导航,或者将handleIconPress改为异步函数,确保读取完成后再执行判断(更推荐前者,减少不必要的状态依赖)。
修改后的MusicScreen代码
const MusicScreen = () => { const navigation = useNavigation(); const handleIconPress = async () => { try { const storedToken = await SecureStore.getItemAsync('token'); console.log(storedToken); // 直接用刚获取的最新token判断跳转 if (storedToken === null) { navigation.navigate('Register'); } else { navigation.navigate('Profile'); } } catch (error) { console.error('Error al obtener el token:', error); // 出错时默认跳注册页或给出提示 navigation.navigate('Register'); } }; return ( <View > <LinearGradient colors={['#c501e2','#fe0ab7','#ae3dff','transparent']} style={styles.Background}> <TouchableOpacity onPress={handleIconPress} style={styles.touchable}> <Image source={require('../files-logos/D-Corchea.png')} style={styles.image}/> </TouchableOpacity> </LinearGradient> </View> )};
补充说明
如果token状态还需在组件其他场景使用,可保留setToken,但跳转逻辑仍需基于刚读取的storedToken:
const MusicScreen = () => { const navigation = useNavigation(); const [token, setToken] = useState(null); const handleIconPress = async () => { try { const storedToken = await SecureStore.getItemAsync('token'); setToken(storedToken); console.log(storedToken); // 用最新读取的storedToken判断,而非state中的token if (storedToken === null) { navigation.navigate('Register'); } else { navigation.navigate('Profile'); } } catch (error) { console.error('Error al obtener el token:', error); navigation.navigate('Register'); } }; return ( // 原有UI代码 )};
修改后,第一次点击即可获取最新token并执行正确的导航逻辑,无需二次点击。
内容的提问来源于stack exchange,提问作者BeastDevMoney
相关产品推荐
相关产品推荐

