React Native跨屏日期显示旧数据错误的解决求助
React Native 页面间日期传递异常问题
我接触React Native开发时间不长,近期遇到一个问题:需要将日历选中的日期数据传递到其他页面。最初尝试页面间直接共享数据但持续报错,于是改用AsyncStorage将日期转为字符串存储的方式实现数据传递,该方法能成功传递数据但存在严重问题:
首次启动应用选择2月1日,跳转页面后日期未显示;返回首页选择2月2日,跳转后页面显示的却是2月1日,即详情页总是显示上一次选中的日期而非当前选中的日期。
代码示例
Home.js
import React from "react"; import { SafeAreaProvider } from "react-native-safe-area-context"; import { Calendar } from "react-native-calendars"; import { View, Alert } from "react-native"; import AsyncStorage from "@react-native-async-storage/async-storage"; var dateString = ""; const savereturndate = async (value) => { try { await AsyncStorage.setItem("selectdate", dateString); } catch (e) { Alert.alert("Error", e, [{ text: "OK", onPress: () => null }]); } }; function HomeScreen({ navigation }) { const markedDates = { "2023-02-01": { marked: true, dotColor: "red" }, }; return ( <SafeAreaProvider> <View> <Calendar markedDates={markedDates} onDayPress={(day) => { for (var key in day) { //console.log("key:" + key + "/" + day[key]) dateString = day[key]; } savereturndate(); navigation.push("Detail"); }} /> </View> </SafeAreaProvider> ); } export default HomeScreen;
Detail.js
import React from "react"; import { SafeAreaProvider } from "react-native-safe-area-context"; import { View, Text, Alert } from "react-native"; import AsyncStorage from "@react-native-async-storage/async-storage"; var returndatedetail = ""; const getreturndate = async () => { try { const hello = await AsyncStorage.getItem("selectdate"); returndatedetail = hello.toString(); } catch (e) { Alert.alert("Error", e, [{ text: "OK", onPress: () => null }]); } }; function DetailScreen() { getreturndate(); return ( <SafeAreaProvider> <View> <Text>{returndatedetail}</Text> </View> </SafeAreaProvider> ); } export default DetailScreen;
开发环境
- OS:macOS Monterey(12.6.3)
- 开发工具:Visual Studio Code (1.71.1)
- 模拟器:iPhone 14 (iOS 16.2)
- React Native版本:9.2.0
- 测试方式:使用Expo Go进行测试
问题原因及修复方案
核心问题
- 异步操作未等待:
savereturndate是异步函数,调用后立刻跳转页面,此时AsyncStorage可能还未完成存储,导致详情页读取旧数据 - 无状态更新触发渲染:直接修改全局变量
returndatedetail,组件不会自动重新渲染,新数据无法显示 - 日期提取错误:遍历
day对象会把最后一个属性(如timestamp)赋值给dateString,而非目标日期字符串
修复步骤
1. 修正Home.js的存储逻辑
- 直接通过
day.dateString获取选中日期,无需遍历 - 等待存储完成后再跳转页面
- 移除全局变量,改用局部变量
修改后的Home.js:
import React from "react"; import { SafeAreaProvider } from "react-native-safe-area-context"; import { Calendar } from "react-native-calendars"; import { View, Alert } from "react-native"; import AsyncStorage from "@react-native-async-storage/async-storage"; const savereturndate = async (date) => { try { await AsyncStorage.setItem("selectdate", date); } catch (e) { Alert.alert("Error", e.toString(), [{ text: "OK", onPress: () => null }]); } }; function HomeScreen({ navigation }) { const markedDates = { "2023-02-01": { marked: true, dotColor: "red" }, }; return ( <SafeAreaProvider> <View> <Calendar markedDates={markedDates} onDayPress={async (day) => { const selectedDate = day.dateString; await savereturndate(selectedDate); navigation.push("Detail"); }} /> </View> </SafeAreaProvider> ); } export default HomeScreen;
2. 修正Detail.js的渲染逻辑
- 使用
useState和useEffect钩子,实现数据读取后自动更新页面 - 处理AsyncStorage返回
null的情况
修改后的Detail.js:
import React, { useState, useEffect } from "react"; import { SafeAreaProvider } from "react-native-safe-area-context"; import { View, Text, Alert } from "react-native"; import AsyncStorage from "@react-native-async-storage/async-storage"; function DetailScreen() { const [selectedDate, setSelectedDate] = useState(""); useEffect(() => { const getreturndate = async () => { try { const date = await AsyncStorage.getItem("selectdate"); if (date) { setSelectedDate(date); } } catch (e) { Alert.alert("Error", e.toString(), [{ text: "OK", onPress: () => null }]); } }; getreturndate(); }, []); return ( <SafeAreaProvider> <View> <Text>{selectedDate || "未选择日期"}</Text> </View> </SafeAreaProvider> ); } export default DetailScreen;
3. 更优方案:直接通过路由传参
无需依赖AsyncStorage,React Navigation支持跳转时直接传递参数,完全避免异步延迟问题:
Home.js修改跳转逻辑:
onDayPress={(day) => { navigation.push("Detail", { selectedDate: day.dateString }); }}
Detail.js接收参数:
function DetailScreen({ route }) { const { selectedDate } = route.params || {}; return ( <SafeAreaProvider> <View> <Text>{selectedDate || "未选择日期"}</Text> </View> </SafeAreaProvider> ); }
内容的提问来源于stack exchange,提问作者Beom
相关产品推荐
相关产品推荐

