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

React Native中AsyncStorage存入useState后map报错求助

解决React Native中AsyncStorage数据存入useState后map报错问题

问题描述

首次尝试React Native开发,尝试将AsyncStorage.getItem获取的数据存入useState后通过map渲染,频繁出现"Error map undefined"错误;但直接在State数组中赋值则可正常运行,已尝试JSON.stringify和JSON.parse仍无法解决。

错误原因分析

  1. 若AsyncStorage中曾存储过非数组格式的数据,JSON.parse后会得到非数组类型,导致调用map时报错;首次运行无存储数据时虽不会触发setValue,但如果解析过程出现异常,也可能导致value变为非数组。
  2. saveOption中直接依赖当前value状态,存在闭包问题,可能导致状态更新不及时或异常。
  3. 组件函数体中直接调用AsyncStorage.getItem属于冗余操作,每次渲染都会执行,无实际作用还可能干扰状态判断。

解决方案及修改后的代码

import { useEffect, useState } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import RadioForm from 'react-native-simple-radio-button';
import AsyncStorage from '@react-native-async-storage/async-storage';

const SelectOption = () => {
  const [value, setValue] = useState([]);

  // 用函数式更新避免闭包导致的状态异常
  const saveOption = (item) => {
    try {
      setValue(prevValue => [...prevValue, {name: item, id: Math.random()}]);
    } catch (e) {
      console.log(e);
    }
  };

  useEffect(() => {
    AsyncStorage.setItem('option', JSON.stringify(value));
  }, [value]);

  useEffect(() => {
    const getOption = async () => {
      try {
        const jsonValue = await AsyncStorage.getItem('option');
        // 确保解析后是数组,无数据则设为空数组
        const parsedData = jsonValue ? JSON.parse(jsonValue) : [];
        // 强制校验类型,非数组则重置为空数组
        setValue(Array.isArray(parsedData) ? parsedData : []);
      } catch (e) {
        console.log(e);
        // 解析出错时也重置为空数组,避免后续渲染报错
        setValue([]);
      }
    };
    getOption();
  }, []);

  const radioProps = [
    {label: 'Option 1', value: 'option1'},
    {label: 'Option 2', value: 'option2'},
    {label: 'Option 3', value: 'option3'}
  ];

  return (
    <View style={styles.sectionContainer}>
      <RadioForm
        radio_props={radioProps}
        initial={0}
        onPress={(selectedValue) => {
          saveOption(selectedValue);
        }}
      />
      {/* 渲染前先判断是否为数组,彻底避免map调用在非数组上 */}
      {Array.isArray(value) && value.map((item) => {
        return <Text key={item.id}>{item.name}</Text>;
      })}
    </View>
  );
};

const styles = StyleSheet.create({
  sectionContainer: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

export default SelectOption;

关键修改点说明

  • 函数式状态更新:saveOption中使用prevValue获取最新状态,解决闭包导致的状态更新异常问题。
  • 严格数据校验:从AsyncStorage取数据时,强制保证最终存入状态的是数组,无数据或解析失败都设置为空数组。
  • 渲染前类型判断:在map执行前增加Array.isArray(value)判断,确保只有数组才会执行遍历渲染。
  • 移除冗余操作:删除组件函数体中直接调用的AsyncStorage.getItem,避免不必要的重复执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 11:46:05