React Native 0.60.6中<Modal/>的onDismiss未触发问题咨询
嘿,我来帮你捋捋这个Modal的问题~
首先说结论:你遇到的情况既不是使用方式有误,也不是完全的Bug,而是React Native 0.60.6版本对iOS pageSheet类型Modal的手势关闭回调支持不完善导致的。
问题根源
在RN 0.60.6里,onDismiss属性的触发逻辑比较局限:它只会在你通过修改visible状态(比如调用willClose把showSetup设为false)来关闭Modal时触发。但当用户用iOS原生的下滑手势关闭pageSheet样式的Modal时,RN并不会自动更新visible状态,也不会触发onDismiss——这是当时版本的一个适配漏洞,后续版本已经修复了。
给你两个可行的解决方案:
方案1:统一关闭逻辑,复用回调
你可以把原本要在onDismiss里执行的逻辑,移到状态更新的回调里,同时确保所有关闭路径(包括按钮触发和手势触发)都走同一个状态更新方法:
// 改写你的willClose方法 willClose = () => { this.setState({ showSetup: false }, () => { alert('onDismiss!'); // 这里放原本onDismiss里的逻辑 }); }; // 调整Modal的属性,让手势关闭也触发willClose <Modal animationType="slide" presentationStyle="pageSheet" visible={this.state.showSetup} hardwareAccelerated onRequestClose={() => this.willClose()} // iOS手势关闭会调用这个方法 > <SetupView closeView={() => this.willClose()} /> </Modal>
不过要注意,部分场景下RN 0.60.6可能不会自动触发onRequestClose,这时候可以试试方案2。
方案2:监听原生Modal隐藏事件
给Modal加个ref,然后监听iOS原生的modalDidHide事件,这样不管是哪种方式关闭Modal,都能捕获到并处理:
// 在类组件的构造函数里创建ref constructor(props) { super(props); this.modalRef = React.createRef(); } // 组件挂载时添加监听 componentDidMount() { if (Platform.OS === 'ios') { this.modalRef.current?.addListener('modalDidHide', () => { // 如果此时showSetup还是true,说明是手势关闭的 if (this.state.showSetup) { this.setState({ showSetup: false }, () => { alert('onDismiss!'); }); } }); } } // 组件卸载时记得移除监听,避免内存泄漏 componentWillUnmount() { if (Platform.OS === 'ios') { this.modalRef.current?.removeListener('modalDidHide'); } } // 给Modal加上ref属性 <Modal ref={this.modalRef} animationType="slide" presentationStyle="pageSheet" visible={this.state.showSetup} hardwareAccelerated onRequestClose={() => this.willClose()} > <SetupView closeView={() => this.willClose()} /> </Modal>
额外建议
如果项目允许的话,升级到React Native 0.63及以上版本会更省心——这个版本之后,onDismiss已经能正确响应iOS的下滑手势关闭操作了,不用额外写这些兼容代码。
内容的提问来源于stack exchange,提问作者jskidd3
相关产品推荐
相关产品推荐

