如何使用useEffect实现注销?Alert弹窗重复触发问题排查
注销页面弹窗重复触发问题解决
原代码与问题现象
// 注销页面
import {Alert} from 'react-native'; import {useEffect} from 'react'; import {useIsFocused} from '@react-navigation/native'; const Logout = props => { const Logout1 = () => { const isFocused = useIsFocused(); Alert.alert('Logout', 'Are you sure you want to logout?', [ { text: 'Cancel', onPress: () => props.navigation.navigate( 'Tabs', { screen: 'HomeScreen', }, ), }, {text: 'Yes', onPress: () => props.navigation.navigate('Login')}, ]); }; useEffect(() => {}, [useIsFocused(), Logout1()]); }; export default Logout;
问题:
期望Alert.alert仅触发1次,但实际触发了2次:
- 点击底部Tab栏的Logout按钮时
- 点击Cancel按钮并跳转到其他页面时,弹窗再次弹出
问题原因
- Hook调用违反规则:
useIsFocused()是React Hook,必须直接在组件顶层调用,不能嵌套在Logout1这类普通函数内部。 - useEffect依赖数组错误:依赖数组里直接执行
Logout1(),会导致组件每次渲染、useIsFocused()返回值变化时都触发弹窗逻辑。 - 无重复触发控制:没有状态标记弹窗是否已显示,页面焦点变化时会重复执行弹窗代码。
修正后的代码
import {Alert} from 'react-native'; import {useEffect, useState} from 'react'; import {useIsFocused} from '@react-navigation/native'; const Logout = props => { const isFocused = useIsFocused(); const [hasShownAlert, setHasShownAlert] = useState(false); const showLogoutAlert = () => { Alert.alert('Logout', 'Are you sure you want to logout?', [ { text: 'Cancel', onPress: () => { props.navigation.navigate('Tabs', {screen: 'HomeScreen'}); setHasShownAlert(false); }, }, { text: 'Yes', onPress: () => { props.navigation.navigate('Login'); setHasShownAlert(false); }, }, ]); }; useEffect(() => { if (isFocused && !hasShownAlert) { setHasShownAlert(true); showLogoutAlert(); } }, [isFocused, hasShownAlert]); return null; }; export default Logout;
修正说明
- 组件顶层调用
useIsFocused(),符合Hook规则的同时正确获取页面焦点状态。 - 新增
hasShownAlert状态,标记弹窗是否已显示,避免焦点变化时重复触发。 useEffect仅在页面获取焦点且未弹窗过时执行弹窗逻辑,确保单次触发。- 点击弹窗按钮后重置
hasShownAlert,保证下次进入注销页面时能正常触发弹窗。
内容的提问来源于stack exchange,提问作者Ahmad Rafi
相关产品推荐
相关产品推荐

