我一直在尝试使用本机反应的Axios,但是遇到了麻烦。 flatList不会呈现数据,而是给我一个警告“警告:列表中的每个孩子都应该有一个唯一的“键”道具。”
我已经在网上寻找了几个小时,找不到解决方案。我能找到的最接近的东西就是设置了keyExtractor。
这是我的代码:
import React, { useEffect, useState } from 'react';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';
import Axios from 'axios';
export default App = () => {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
useEffect(() => {
Axios.get('https://reactnative.dev/movies.json')
.then(({data}) => setData({data}))
.catch((error) => console.error(error))
.finally(() => setLoading(false));
});
return (
<View style={{ flex: 1, padding: 24 }}>
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={JSON.stringify(data)}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => (
<Text>{item.title}, {item.releaseYear}</Text>
)}
/>
)}
</View>
);
};
我知道这可能是一个非常简单的问题,但是如果您能帮助我,我将非常感激。
我认为值得一提的是它可以与fetch一起使用。因此,我认为问题出在axios.get请求,而不是flatList。
如果有任何用途,请参见以下API:
{
"title": "The Basics - Networking",
"description": "Your app fetched this from a remote endpoint!",
"movies": [
{ "id": "1", "title": "Star Wars", "releaseYear": "1977" },
{ "id": "2", "title": "Back to the Future", "releaseYear": "1985" },
{ "id": "3", "title": "The Matrix", "releaseYear": "1999" },
{ "id": "4", "title": "Inception", "releaseYear": "2010" },
{ "id": "5", "title": "Interstellar", "releaseYear": "2014" }
]
}
编辑:尝试了这里的答案后,它停止发出警告,但呈现了一个空列表。
答案 0 :(得分:1)
我认为您需要日志数据进行调试。
第一:setData({data})
是错误的。
第二:不要使用JSON.stringify(data)
。
第三:keyExtractor={({ id }, index) => id}
错误
在下面尝试此代码
import React, { useEffect, useState } from 'react';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';
import Axios from 'axios';
export default App = () => {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
useEffect(() => {
Axios.get('https://reactnative.dev/movies.json')
.then(({ data }) => {
console.log("defaultApp -> data", data.movies)
setData(data.movies)
})
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, []);
return (
<View style={{ flex: 1, padding: 24 }}>
{isLoading ? <ActivityIndicator /> : (
<FlatList
data={data}
keyExtractor={(item, index) => {
// console.log("index", index)
return index.toString();
}}
renderItem={({ item }) => {
console.log("item", item)
return (
<Text style={{ flex: 1, backgroundColor: 'red' }}>{item.title}, {item.releaseYear}</Text>
)
}}
/>
)}
</View>
);
};
答案 1 :(得分:0)
在渲染项目中,您需要提供文本键:
renderItem={({ item }) => (
<Text key={item.title}>{item.title}, {item.releaseYear}</Text>
)}
假设item.title是唯一的,就是这样。
要提供更多有关此问题原因的上下文,那就是react使用键来标识渲染之间列表中的哪些项目是相同的,因此与在每个渲染上创建新项目相比,它可以做的工作更少。本质上,React使用键来确定哪些元素是同一元素。因此,如果您在每个渲染之间更改一个键,则react将假定该元素是一个新元素,并在安装新元素之前先卸载旧元素。
可以使用索引作为键,但是性能不如使用唯一标识符。因为使用索引意味着如果对列表进行排序或以其他方式进行重新排序,则不仅要移动dom节点,还需要做更多的工作来协调差异。
编辑: 除了最初的问题,我已经解决了您遇到的其他问题。
useEffect
调用需要使用依赖项数组,因此不会每次重新呈现时都被调用。
axios调用中的数据需要使用data.movies才能获得电影数组。
传递到FlatList的数据不需要进行字符串化处理,因为这会导致将每个字符串化的字符呈现为新行(逗号)。
答案 2 :(得分:0)
尝试
FlatList
data={JSON.stringify(data)}
keyExtractor={(id, index) => index.toString()}
renderItem={({ item }) => (
<Text>{item.title}, {item.releaseYear}</Text>
)}
/>
答案 3 :(得分:0)
keyExtractor={({ id }, index) => id.toString()}
密钥最初以数字形式出现,您必须将其转换为字符串。