React Native iOS端关闭首个Modal后打开第二个Modal的问题
针对iOS端React Native多Modal切换问题的解决方案
以下是几个无需依赖setTimeout的可靠方案,解决关闭第一个Modal后打开第二个无响应的问题:
方案1:使用原生Modal的onDismiss回调(推荐)
React Native原生Modal组件在iOS平台提供了onDismiss回调,该回调会在Modal完全关闭(包括退场动画结束)时触发,刚好匹配你的需求。直接在第一个Modal上绑定此回调,在回调中打开第二个Modal即可。
示例代码:
import { useState } from 'react'; import { Modal, View, Button } from 'react-native'; const MultiModalDemo = () => { const [showFirstModal, setShowFirstModal] = useState(false); const [showSecondModal, setShowSecondModal] = useState(false); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Button title="打开第一个Modal" onPress={() => setShowFirstModal(true)} /> <Modal visible={showFirstModal} animationType="slide" onDismiss={() => setShowSecondModal(true)} > <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Button title="关闭第一个Modal" onPress={() => setShowFirstModal(false)} /> </View> </Modal> <Modal visible={showSecondModal} animationType="slide"> <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Button title="关闭第二个Modal" onPress={() => setShowSecondModal(false)} /> </View> </Modal> </View> ); }; export default MultiModalDemo;
注:onDismiss仅iOS生效,Android可配合onRequestClose回调做兼容,保证跨平台行为一致。
方案2:状态监听 + requestAnimationFrame
通过监听第一个Modal的可见状态变化,当状态变为false时,用requestAnimationFrame将打开第二个Modal的操作推迟到下一次UI渲染周期,确保第一个Modal的退场动画完全结束后再执行后续操作,比setTimeout更贴合UI渲染机制,无固定延迟的隐患。
示例代码:
import { useState, useEffect } from 'react'; import { Modal, View, Button } from 'react-native'; const MultiModalDemo = () => { const [showFirstModal, setShowFirstModal] = useState(false); const [showSecondModal, setShowSecondModal] = useState(false); useEffect(() => { if (!showFirstModal) { const rafId = requestAnimationFrame(() => { setShowSecondModal(true); }); return () => cancelAnimationFrame(rafId); } }, [showFirstModal]); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Button title="打开第一个Modal" onPress={() => setShowFirstModal(true)} /> <Modal visible={showFirstModal} animationType="slide"> <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Button title="关闭第一个,打开第二个" onPress={() => setShowFirstModal(false)} /> </View> </Modal> <Modal visible={showSecondModal} animationType="slide"> <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Button title="关闭第二个Modal" onPress={() => setShowSecondModal(false)} /> </View> </Modal> </View> ); }; export default MultiModalDemo;
方案3:基于react-native-modal库的状态监听
如果你使用的是第三方react-native-modal库,可通过监听其isVisible状态变化,结合requestAnimationFrame确保动画完成后再切换Modal,替代已移除的onModalHide回调。
示例代码:
import { useState, useEffect } from 'react'; import Modal from 'react-native-modal'; import { View, Button } from 'react-native'; const MultiModalDemo = () => { const [firstModalVisible, setFirstModalVisible] = useState(false); const [secondModalVisible, setSecondModalVisible] = useState(false); useEffect(() => { if (!firstModalVisible) { const rafId = requestAnimationFrame(() => { setSecondModalVisible(true); }); return () => cancelAnimationFrame(rafId); } }, [firstModalVisible]); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Button title="打开第一个Modal" onPress={() => setFirstModalVisible(true)} /> <Modal isVisible={firstModalVisible}> <View style={{ padding: 20, backgroundColor: 'white', borderRadius: 10 }}> <Button title="关闭第一个,打开第二个" onPress={() => setFirstModalVisible(false)} /> </View> </Modal> <Modal isVisible={secondModalVisible}> <View style={{ padding: 20, backgroundColor: 'white', borderRadius: 10 }}> <Button title="关闭第二个Modal" onPress={() => setSecondModalVisible(false)} /> </View> </Modal> </View> ); }; export default MultiModalDemo;
内容的提问来源于stack exchange,提问作者Quantal
相关产品推荐
相关产品推荐

