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

React Native中如何将AsyncStorage的JSON数据绑定到FlatList

问题修正点与修改方案

  • 修正状态初始值:FlatList的data属性仅接受数组类型,原代码初始值设为布尔值true会直接导致渲染异常,将状态初始值改为空数组,同时调整状态名提升可读性。
  • 包裹异步请求逻辑:原代码直接在组件顶层调用AsyncStorage.getItem,会在每次组件重渲染时重复触发请求,更新状态后又再次触发重渲染,陷入死循环。用useEffect加空依赖包裹该逻辑,保证仅在组件挂载时执行一次。
  • 解析存储的字符串数据:AsyncStorage仅支持存储字符串类型,取出的JSON字符串需要通过JSON.parse转换为JS对象才能正常使用。
  • 取正确层级的列表数据:存储的对象结构中,users字段才是FlatList需要的数组,不能直接将整个对象赋值给data属性。
  • 补充keyExtractor属性:FlatList要求每个列表项绑定唯一key,避免性能警告,直接使用每项的id作为唯一标识即可。

修改后完整代码

import React, { useState, useEffect } from 'react';
import { SafeAreaView, StyleSheet, View, Text, Image, Alert, TouchableOpacity } from 'react-native';
import { FlatList } from 'react-native-gesture-handler';
import Icon from 'react-native-vector-icons/MaterialIcons';
import COLORS from '../../consts/colors';
import foods from '../../consts/foods';
import { PrimaryButton } from '../components/Button';
import AsyncStorage from '@react-native-async-storage/async-storage';

const CartScreen = ({ navigation }) => {
  // 调整状态初始值与命名
  const [userList, setUserList] = useState([]);

  // 异步逻辑放入useEffect,仅挂载执行一次
  useEffect(() => {
    const fetchStoredData = async () => {
      try {
        const value = await AsyncStorage.getItem('storeddata');
        if (value) {
          // 解析字符串为对象,提取users数组
          const parsedData = JSON.parse(value);
          setUserList(parsedData.users || []);
          console.log("saveddata", parsedData);
        }
      } catch (e) {
        console.log("读取存储数据失败", e);
      }
    };
    fetchStoredData();
  }, []);

  const CartCard = ({ item }) => {
    console.log("itemlist", item);
    return (
      <View style={style.cartCard}>
        <Image source={{ uri: item.image }} style={{ height: 80, width: 80 }} />
        <View
          style={{
            height: 100,
            marginLeft: 10,
            paddingVertical: 20,
            flex: 1,
          }}>
          <Text style={{ fontWeight: 'bold', fontSize: 16 }}>{item.title}</Text>
          <Text style={{ fontSize: 13, color: COLORS.grey }}>
            {item.title}
          </Text>
          <Text style={{ fontSize: 17, fontWeight: 'bold' }}>${item.id}</Text>
        </View>
        <View style={{ marginRight: 20, alignItems: 'center' }}>
          <Text style={{ fontWeight: 'bold', fontSize: 18 }}>5</Text>
          <View style={style.actionBtn}>
            <Icon name="remove" size={25} color={COLORS.white} />
            <Icon name="add" size={25} color={COLORS.white} />
          </View>
        </View>
      </View>
    );
  };
  return (
    <SafeAreaView style={{ backgroundColor: COLORS.white, flex: 1 }}>
      <View style={style.header}>
        <Icon name="arrow-back-ios" size={28} onPress={navigation.goBack} />
        <Text style={{ fontSize: 20, fontWeight: 'bold' }}>Cart</Text>
      </View>
      <FlatList
        showsVerticalScrollIndicator={false}
        contentContainerStyle={{ paddingBottom: 80 }}
        data={userList}
        // 添加keyExtractor指定唯一key
        keyExtractor={item => item.id.toString()}
        renderItem={({ item }) => <CartCard item={item} />}
        ListFooterComponentStyle={{ paddingHorizontal: 20, marginTop: 20 }}
        ListFooterComponent={() => (
          <View>
            <View
              style={{
                flexDirection: 'row',
                justifyContent: 'space-between',
                marginVertical: 15,
              }}>
              <Text style={{ fontSize: 18, fontWeight: 'bold' }}>
                Total Price
              </Text>
              <Text style={{ fontSize: 18, fontWeight: 'bold' }}>$50</Text>
            </View>
            <View style={{ marginHorizontal: 30 }}>
              <PrimaryButton title="CHECKOUT" onPress={() => navigation.navigate('Checkout')} />
            </View>
          </View>
        )}
      />
    </SafeAreaView>
  );
};
const style = StyleSheet.create({
  header: {
    paddingVertical: 20,
    flexDirection: 'row',
    alignItems: 'center',
    marginHorizontal: 20,
  },
  cartCard: {
    height: 100,
    elevation: 15,
    borderRadius: 10,
    backgroundColor: COLORS.white,
    marginVertical: 10,
    marginHorizontal: 20,
    paddingHorizontal: 10,
    flexDirection: 'row',
    alignItems: 'center',
  },
  actionBtn: {
    width: 80,
    height: 30,
    backgroundColor: COLORS.primary,
    borderRadius: 30,
    paddingHorizontal: 5,
    flexDirection: 'row',
    justifyContent: 'center',
    alignContent: 'center',
  },
});

export default CartScreen;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 10:57:02