React Native:导航返回按钮触发弹窗,自定义按钮返回不触发问题
React Native 解决自定义确认按钮返回触发未保存弹窗的问题
你遇到的问题主要有两个原因:
- React的
setState是异步更新的,点击confirm按钮后立刻调用navigation.goBack()时,buttonClicked状态还没完成更新,导致拦截逻辑依然触发。 - 拦截逻辑的条件判断错误,使用了
&&而非||,无法正确识别自定义按钮的点击操作。
修复步骤及代码
1. 纠正拦截逻辑的条件判断
在beforeRemove监听器中,只要满足「无未保存内容」或「点击了自定义确认按钮」任一条件,就直接放行返回操作,不需要弹窗:
if (!hasUnsavedChanges || buttonClicked) { return; }
2. 解决setState异步问题
通过useEffect监听buttonClicked状态变化,确保状态更新完成后再执行返回操作,同时重置状态避免残留影响:
const EditTextScreen = ({ navigation }) => { const [text, setText] = React.useState(''); const [buttonClicked, setButtonClicked] = React.useState(false); const hasUnsavedChanges = Boolean(text); // 监听buttonClicked状态,触发返回并重置状态 React.useEffect(() => { if (buttonClicked) { navigation.goBack(); setButtonClicked(false); } }, [buttonClicked, navigation]); React.useEffect( () => navigation.addListener('beforeRemove', (e) => { const action = e.data.action; // 条件改为:无未保存内容 或 点击了确认按钮,直接放行 if (!hasUnsavedChanges || buttonClicked) { return; } e.preventDefault(); Alert.alert( 'Discard changes?', 'You have unsaved changes. Are you sure to discard them and leave the screen?', [ { text: "Don't leave", style: 'cancel', onPress: () => {} }, { text: 'Discard', style: 'destructive', onPress: () => navigation.dispatch(action), }, ] ); }), [hasUnsavedChanges, buttonClicked, navigation] ); return ( <View style={styles.content}> <TextInput autoFocus style={styles.input} value={text} placeholder="Type something…" onChangeText={setText} /> {/* 点击按钮仅更新状态,返回操作由useEffect处理 */} <Button onPress={() => setButtonClicked(true)}>confirm</Button> </View> ); };
说明
- 自定义确认按钮点击时仅更新
buttonClicked状态,useEffect监听到状态变化后执行返回,此时buttonClicked已为true,拦截逻辑会直接放行。 - 执行返回后重置
buttonClicked为false,避免再次进入该页面时状态残留导致异常。
内容的提问来源于stack exchange,提问作者user23375549
相关产品推荐
相关产品推荐

