我具有要从AsyncStorage检索的以下对象,并且希望将其显示在FlatList
中,但出现以下错误:
不变违规:不变违规:不变违规:不变违规:试图获取超出范围索引NaN的帧
我的JSON格式是:
Object {
"44": Object {
"pro_id": "44",
"pro_img": "url",
"pro_name": " S4 ",
},
"52": Object {
"pro_id": "52",
"pro_img": "url",
"pro_name": " S4 ",
},
}
从AsyncStorage
中检索上述JSON,如下所示:
retrieveData = async () => {
try {
await AsyncStorage.getItem('userFavorites')
.then(req => JSON.parse(req))
.then(json => this.setState({ favPro:json }))
} catch (error) {
}
}
我在FlatList
中呈现项目的方法是这样定义的:
fav = ({ item }) => {
return (
<View>
<Text>{item.pro_id+ item.pro_name}</Text>
</View>
)
}
最后,我将FlatList
渲染如下:
<FlatList
data={this.state.favPro}
renderItem={this.fav}
keyExtractor={item => item.pro_id}
/>
如何使用FlatList
组件显示JSON数据?
答案 0 :(得分:3)
FlatList
组件需要data
道具的数组输入。根据您的JSON格式,似乎您正在传递的是对象而不是数组。
请考虑对渲染方法进行以下调整:
// Convert object to array based on it's values. If favPro not
// valid (ie during network request, default to an empty array)
const data = this.state.favPro ? Object.values(this.state.favPro) : []
<FlatList
data={data}
renderItem={this.fav}
keyExtractor={item => item.pro_id}
/>
答案 1 :(得分:2)
您使用的async / await
错误。无需调用.then
,而是将对await
的调用分配给一个变量(如果不返回值,则不分配它),然后将调用(或多个调用)包装到await
在try / catch
块中。关键字await将自动处理resolve
和reject
,以便您获取适当的信息。
retrieveData = async () => {
try {
const data = JSON.parse(await AsyncStorage.getItem("userFavorites"))
this.setState({ favPro: data })
} catch (error) {
console.error(error)
this.setState({ favPro: [] })
}
}
您还需要传递一个数组,数据的形状看起来像一个对象,但是它应该是一个对象数组。这并不是一个非常困难的转换,如果需要,我可以提供一个辅助功能。
编辑:如果需要将对象转换为数组,则可以使用reduce
函数
const data = {
'44': { a: 2 },
'55': { b: 3 },
}
const dataArr = Object.keys(data).reduce(
(arr, key) => arr.concat(data[key]),
[]
)
通过使用Object.keys
,我们可以按名称命名每个对象。然后调用reduce
和Object.keys
返回的数组,将函数作为第一个参数,并将空数组作为第二个参数。第二个参数作为第一个参数arr
自动传递给函数,而我们传递的函数的第二个参数是对象的键。然后,只需使用concat
将对象添加到数组中即可。
Array.reduce
乍一看似乎有点让人不知所措,但这是一种非常强大的方法,您可以完成很多工作。