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

React Native AsyncStorage挂载时无法更新状态问题求助

问题根源

  1. useEffect语法错误:直接在useEffect回调中使用await但未将回调声明为async函数,导致异步代码无法正常执行,数据根本没加载到状态中,组件一直沿用初始值。
  2. 渲染未处理加载状态:AsyncStorage是异步操作,组件会先以初始状态渲染,若numExercise对应的索引超出初始weights的范围(比如初始weights仅1个元素,但numExercise取值为1),会导致weights[numExercise]为undefined,调用map时触发错误。

解决方案

1. 修复useEffect异步逻辑

将异步加载逻辑封装到内部async函数中执行,确保代码正常运行:

const WorkoutScreen = ({ navigation, route }) => {
  const [workoutName, setWorkoutName] = useState("");
  const [exercisesArr, setExercisesArr] = useState([""]);
  const [weights, setWeights] = useState([[""]]);
  const [reps, setReps] = useState([[""]]);
  const [restTimers, setRestTimers] = useState([""]);
  const [isLoading, setIsLoading] = useState(true); // 添加加载状态

  useEffect(() => {
    const loadWorkoutData = async () => {
      try {
        console.log("loading workoutscreen data for:", route.params.name);
        const unparsedWorkoutData = await AsyncStorage.getItem(route.params.name);

        if (unparsedWorkoutData !== null) {
          const workoutData = JSON.parse(unparsedWorkoutData);

          setWorkoutName(route.params.name.toString());
          setExercisesArr(workoutData[0]);
          setWeights(workoutData[1]);
          setReps(workoutData[2]);
          setRestTimers(workoutData[3]);
        }
      } catch (error) {
        console.log("ERROR LOADING DATA:", error);
      } finally {
        setIsLoading(false); // 标记加载完成
      }
    };

    loadWorkoutData();
  }, []);

  // 后续代码
};

2. 避免渲染时访问undefined

方案一:通过加载状态控制渲染,数据加载完成后再渲染目标组件

return (
  <View>
    {isLoading ? (
      <Text>加载中...</Text>
    ) : (
      weights[numExercise]?.map((weight, i) => {
        return (
          <SetComponent
            key={i}
            numSet={i}
            numExercise={numExercise}
            prevWeights={prevWeights}
            weights={weights}
            setWeights={setWeights}
            prevReps={prevReps}
            reps={reps}
            setReps={setReps}
            isDoneArr={isDoneArr}
            setIsDoneArr={setIsDoneArr}
          />
        );
      })
    )}
  </View>
);

方案二:用兜底值处理undefined,即使索引越界也不会报错

return (
  <View>
    {(weights[numExercise] || []).map((weight, i) => {
      return (
        <SetComponent
          key={i}
          numSet={i}
          numExercise={numExercise}
          prevWeights={prevWeights}
          weights={weights}
          setWeights={setWeights}
          prevReps={prevReps}
          reps={reps}
          setReps={setReps}
          isDoneArr={isDoneArr}
          setIsDoneArr={setIsDoneArr}
        />
      );
    })}
  </View>
);

3. 校验numExercise的有效性

确保numExercise的取值在weights的索引范围内,比如在数据加载完成后修正其值:

const [numExercise, setNumExercise] = useState(0);

useEffect(() => {
  if (!isLoading && weights.length > 0) {
    setNumExercise(prev => Math.min(prev, weights.length - 1));
  }
}, [isLoading, weights.length]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 20:54:22