React Native:将Alpha Vantage API数据渲染到FlatList时遇报错求助
解决Alpha Vantage数据在FlatList中展示的报错问题
问题场景与报错
尝试用FlatList展示Alpha Vantage TIME_SERIES_INTRADAY接口返回的「Time Series (5min)」数据时,出现以下报错:
Objects are not valid as a React child (found: object with keys {1. open, 2. high, 3. low, 4. close, 5. volume}). If you meant to render a collection of children, use an array instead.
报错原因
- 直接在
<Text>组件中渲染了item对象,React Native的<Text>仅支持字符串、数字等原始类型,无法直接渲染对象。 keyExtractor使用item.id,但接口返回的数据项中不存在id字段,会导致key缺失警告。
解决方案
1. 重构数据结构,保留时间戳
原代码用Object.values()仅提取行情数据,丢失了唯一的时间戳信息。需将键值对转换为包含时间戳和行情数据的数组:
const timeSeriesData = data['Time Series (5min)']; const formattedData = Object.entries(timeSeriesData).map(([timestamp, values]) => ({ timestamp, ...values })); setListing(formattedData);
2. 修改renderItem,渲染具体字段
拆分对象中的每个字段,用<Text>分别展示:
renderItem={({item}) => ( <TouchableOpacity onPress={() => {}}> <Text style={styles.output}>时间: {item.timestamp}</Text> <Text style={styles.output}>开盘价: {item['1. open']}</Text> <Text style={styles.output}>最高价: {item['2. high']}</Text> <Text style={styles.output}>最低价: {item['3. low']}</Text> <Text style={styles.output}>收盘价: {item['4. close']}</Text> <Text style={styles.output}>成交量: {item['5. volume']}</Text> <View style={{height: 12, backgroundColor: '#f0f0f0'}} /> </TouchableOpacity> )}
3. 修正keyExtractor
使用时间戳作为唯一key:
keyExtractor={item => item.timestamp}
修改后的完整代码
import React, { useState, useEffect } from 'react'; import { View, Text, FlatList, ActivityIndicator, TouchableOpacity, StyleSheet } from 'react-native'; const Rename = () => { const [listing, setListing] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { getProduct(); }, []); const getProduct = () => { const url = 'https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=IBM&interval=5min&apikey=demo'; fetch(url) .then((response) => { if (!response.ok) { throw new Error('请求失败'); } return response.json(); }) .then((data) => { const timeSeriesData = data['Time Series (5min)']; // 转换数据结构,保留时间戳 const formattedData = Object.entries(timeSeriesData).map(([timestamp, values]) => ({ timestamp, ...values })); setListing(formattedData); setIsLoading(false); }) .catch((error) => { setError(error.message); setIsLoading(false); }); }; return ( <View style={styles.container}> {isLoading ? ( <ActivityIndicator color={'#000'} size='large' /> ) : error ? ( <Text style={styles.errorText}>{error}</Text> ) : ( <FlatList data={listing} renderItem={({ item }) => ( <TouchableOpacity style={styles.itemContainer}> <Text style={styles.text}>时间: {item.timestamp}</Text> <Text style={styles.text}>开盘价: {item['1. open']}</Text> <Text style={styles.text}>最高价: {item['2. high']}</Text> <Text style={styles.text}>最低价: {item['3. low']}</Text> <Text style={styles.text}>收盘价: {item['4. close']}</Text> <Text style={styles.text}>成交量: {item['5. volume']}</Text> </TouchableOpacity> )} keyExtractor={item => item.timestamp} /> )} </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 16, backgroundColor: '#fff' }, itemContainer: { padding: 12, borderBottomWidth: 1, borderBottomColor: '#eee' }, text: { fontSize: 14, marginBottom: 4 }, errorText: { fontSize: 16, color: '#ff3333', textAlign: 'center', marginTop: 20 } }); export default Rename;
内容的提问来源于stack exchange,提问作者cOd3
相关产品推荐
相关产品推荐

