You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 17:06:06