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

React Native Async Storage数据加载异常问题求助

React Native成绩计算应用科目显示延迟问题

我正在开发一款React Native成绩计算应用,支持创建科目并为每个科目添加成绩,包含多个页面。数据以字典形式存储在Async Storage中,格式示例:

{
  "subject 1": [grades],
  "subject 2": [grades]
}

实际存储示例:

{
  "math": [1,4,2],
  "english": [5,2]
}

当前遇到的问题:添加新科目后,界面仅显示上一个科目;再次添加新科目时,才会显示刚添加的那个科目。

App.js 代码

import { React, useEffect, useState } from "react";
import { StyleSheet } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import Homescreen from "./screens/Homescreen";
import NewSubject from "./screens/NewSubject";
import ShowSubject from "./screens/ShowSubject";
import AsyncStorage from "@react-native-async-storage/async-storage";

const Stack = createNativeStackNavigator();

export default function App() {
  let [dict, setDict] = useState({});

  useEffect(() => {
    loadDictionary().then(res => {
      setDict(res);
    });
  }, []);

  useEffect(() => {
    safeDictionary();
  }, [dict]);

  async function loadDictionary() {
    const value = await AsyncStorage.getItem('dict');
    try {
      if (value) {
        return JSON.parse(value);
      }
      return ({});
    } catch (error) {
      console.log("GET ERROR AT LOAD DICTONARY: ", error)
    }
  }

  async function safeDictionary() {
    try {
      await AsyncStorage.setItem("dict", JSON.stringify(dict));
    } catch (error) {
      console.log("GET ERROR AT SAFE DICTONARY:", error);
    }
  }

  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen
          name="Home"
          component={Homescreen}
          options={{ title: "Grades Calculator" }}
          initialParams={{ dict, setDict }}
        />
        <Stack.Screen name="New Subject" component={NewSubject} initialParams={{ dict, setDict }} />
        <Stack.Screen name="Subject" component={ShowSubject} initialParams={{ dict, setDict }}/>
      </Stack.Navigator>
    </NavigationContainer>
  );
}

问题原因

核心问题是**initialParams仅在组件首次挂载时传递参数**,后续App组件中dict更新后,子组件(如Homescreen)不会自动获取最新值——它拿到的始终是初始化时的旧dict,只有当组件重新挂载时才会读取新参数,这就导致了"延迟显示"的现象。

修复方案

方案1:使用React Context共享状态(推荐)

将状态和状态更新方法放到Context中,让所有需要的组件直接获取最新状态,无需依赖路由参数。

  1. 创建SubjectContext.js
import { createContext, useContext, useState, useEffect } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';

const SubjectContext = createContext();

export function SubjectProvider({ children }) {
  const [dict, setDict] = useState({});

  useEffect(() => {
    loadDictionary().then(res => setDict(res));
  }, []);

  useEffect(() => {
    safeDictionary();
  }, [dict]);

  async function loadDictionary() {
    const value = await AsyncStorage.getItem('dict');
    try {
      return value ? JSON.parse(value) : {};
    } catch (error) {
      console.log("GET ERROR AT LOAD DICTONARY: ", error);
      return {};
    }
  }

  async function safeDictionary() {
    try {
      await AsyncStorage.setItem("dict", JSON.stringify(dict));
    } catch (error) {
      console.log("GET ERROR AT SAFE DICTONARY:", error);
    }
  }

  return (
    <SubjectContext.Provider value={{ dict, setDict }}>
      {children}
    </SubjectContext.Provider>
  );
}

export function useSubjects() {
  return useContext(SubjectContext);
}
  1. 修改App.js,用Context包裹导航容器
import { React } from "react";
import { StyleSheet } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import Homescreen from "./screens/Homescreen";
import NewSubject from "./screens/NewSubject";
import ShowSubject from "./screens/ShowSubject";
import { SubjectProvider } from './SubjectContext';

const Stack = createNativeStackNavigator();

export default function App() {
  return (
    <SubjectProvider>
      <NavigationContainer>
        <Stack.Navigator>
          <Stack.Screen
            name="Home"
            component={Homescreen}
            options={{ title: "Grades Calculator" }}
          />
          <Stack.Screen name="New Subject" component={NewSubject} />
          <Stack.Screen name="Subject" component={ShowSubject} />
        </Stack.Navigator>
      </NavigationContainer>
    </SubjectProvider>
  );
}
  1. 在子组件中使用Context
    比如Homescreen.js:
import { useSubjects } from '../SubjectContext';

function Homescreen() {
  const { dict } = useSubjects();
  // 这里的dict会自动同步最新状态,界面实时更新

  return (
    // 你的界面渲染代码
  );
}

NewSubject.js中更新状态:

import { useSubjects } from '../SubjectContext';

function NewSubject({ navigation }) {
  const { setDict } = useSubjects();

  const addSubject = (subjectName) => {
    setDict(prev => ({
      ...prev,
      [subjectName]: []
    }));
    navigation.goBack();
  };

  // 你的界面代码
}

方案2:监听页面焦点重新加载数据(临时修复)

如果不想重构为Context,可以在Homescreen中监听页面焦点,每次获取焦点时重新读取AsyncStorage数据:

import { useState, useEffect } from 'react';
import { useFocusEffect } from '@react-navigation/native';
import AsyncStorage from '@react-native-async-storage/async-storage';

function Homescreen({ route }) {
  const [dict, setDict] = useState({});
  const { setDict: parentSetDict } = route.params;

  useFocusEffect(
    React.useCallback(() => {
      async function reloadData() {
        const value = await AsyncStorage.getItem('dict');
        if (value) {
          const newDict = JSON.parse(value);
          setDict(newDict);
          parentSetDict(newDict);
        }
      }
      reloadData();
    }, [parentSetDict])
  );

  // 你的界面代码
}

内容的提问来源于stack exchange,提问作者Rannaery

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 06:15:39