使用session storage实现移动应用每日仅展示一次弹窗的问题咨询
问题原因和修复方案
1 核心报错原因
- React Native(Expo)运行在原生移动端环境,不存在浏览器的
window全局对象,也没有window.sessionStorageAPI,直接调用必然抛出引用错误 - 你选择的sessionStorage本身也不符合「每日仅展示一次」的需求:sessionStorage是会话级存储,应用退出后就会清空,且本身没有过期时间控制,无法实现按自然天判断展示逻辑
2 正确实现方案
Expo环境推荐用@react-native-async-storage/async-storage做本地持久化存储,同时调整代码执行时机和判断逻辑:
第一步安装依赖
执行命令:npx expo install @react-native-async-storage/async-storage
第二步调整代码逻辑
- 弹窗显示的判断逻辑要放到
useEffect钩子中,在组件挂载完成后执行,避免渲染时触发状态更新导致死循环 - 存储时需要同时保存展示当天的时间戳,下次打开时对比当前日期和存储的日期,不是同一天就重新展示弹窗
完整参考代码如下:
import AsyncStorage from '@react-native-async-storage/async-storage'; import { useState, useEffect } from 'react'; // 组件内代码 const [modalVisible, setModalVisible] = useState(false); // 默认不显示,等判断后再决定 useEffect(() => { const checkModalStatus = async () => { try { // 获取存储的上次展示日期 const lastShowDate = await AsyncStorage.getItem('modalLastShowDate'); const today = new Date().toDateString(); // 转成日期字符串,仅对比年月日 // 如果上次展示日期不是今天,就显示弹窗 if (lastShowDate !== today) { setModalVisible(true); } } catch (err) { console.log('读取存储失败:', err.message); } }; checkModalStatus(); }, []); // 弹窗关闭时的通用方法,避免重复代码 const handleModalClose = async () => { try { // 存储今天的日期 await AsyncStorage.setItem('modalLastShowDate', new Date().toDateString()); } catch (err) { console.log('存储失败:', err.message); } setModalVisible(false); }; // 渲染部分的弹窗代码 {modalVisible && <View style={styles.centeredView}> <Modal animationType="fade" transparent={false} visible={modalVisible} onRequestClose={() => { props.navigation.navigate(props.route.params.navTo); handleModalClose(); }} > <View style={styles.centeredView}> <View style={styles.modalView}> <Text style={styles.modalText}>请记得每日填写调研问卷</Text> <TouchableHighlight style={[styles.YesButton, styles.YesButtonClose]} onPress={async () => { try { await WebBrowser.openBrowserAsync('SURVEY'); } catch (err) { console.log(err.message); } handleModalClose(); }} > <Text style={styles.textStyle}>完成调研</Text> </TouchableHighlight> <TouchableHighlight style={[styles.NoButton, styles.NoButtonClose]} onPress={async () => { try { await manderleySurveyGet(); } catch (err) { console.log(err.message); } handleModalClose(); }} > <Text style={styles.textStyle}>我已完成调研</Text> </TouchableHighlight> </View> </View> </Modal> </View>}
3 原代码其他问题修复
- 修复了第一个按钮
onPress开头多余的.catch语法错误 - 统一了异步操作的错误捕获逻辑,避免异步报错导致应用崩溃
- 把重复的存储和关闭弹窗逻辑抽成通用方法,减少冗余代码
内容的提问来源于stack exchange,提问作者Davospike
相关产品推荐
相关产品推荐

