我有一个feedItems
数组。我想根据axios
获取请求的响应来设置这个数组的项。在屏幕中,我想显示这个数组元素的信息。所以,在做任何事情之前,我必须设置这个数组,这样我就可以显示这个数组元素的信息。
我在发出API请求时没有问题,我确信response.data
不是空的。但是,当我使用setFeedItems(...feedItems, response.data[i]);
函数时,我会得到以下错误。
[未处理的承诺拒绝:类型错误:传播不可迭代实例的尝试无效。]
这是代码:
const [feedItems, setFeedItems] = useState([{}]);
useEffect(async () => {
console.log("here");
let accessToken = await AsyncStorage.getItem("accessToken");
const response = await axios
.get(
"http://repor****-env-1.eba-nj*******/feed",
{
headers: {
Authorization: "Bearer " + accessToken,
},
}
)
.then((response) => {
for (let i = 0; i < response.data.length; i++) {
setFeedItems(...feedItems, response.data[i]);
}
//console.log(feedArray);
console.log(feedItems);
});
}, []);
问题是将[{}]
扩展为setFeedItems
的离散参数。要将response.data
附加到feeditems
,请执行以下操作:
.then((response) => {
setFeedItems(feedItems => [...feedItems, ...response.data]);
// No `console.log(feedItems)` here, it will show you outdated information
});
注意:
- 使用回调表单,因为您正在根据现有状态更新状态,所以您希望确保使用最新状态
[]
围绕返回值,因此您正在创建一个数组并将项分散到其中- 它正在将旧的
feedItems
和新的response.data
扩展到新的阵列中
但如果您想用response.data
中的数据替换feedItems
(在这种特定情况下,您可能会这样做(,它更简单:
.then((response) => {
setFeedItems(response.data);
// No `console.log(feedItems)` here, it will show you outdated information
});
此外,在正常情况下,feedItems
将以空数组开始,而不是其中包含空对象的数组
const [feedItems, setFeedItems] = useState([]);
另外:useEffect
不会对async
函数返回的promise做任何有用的事情(并且会查看返回值,看看它是否是一个函数(,所以你不应该向它传递async
函数。由于你已经在使用显式promise回调,所以没有理由使用await
和async
函数。此外,你应该处理拒绝承诺的问题。
将所有这些放在一起(使用"替换"而不是"附加"选项(:
const [feedItems, setFeedItems] = useState([{}]);
useEffect(() => {
AsyncStorage.getItem("accessToken").
then(accessToken => axios.get(
"http://repor****-env-1.eba-nj*******/feed",
{
headers: {
Authorization: "Bearer " + accessToken,
},
}))
.then((response) => {
setFeedItems(feedItems => [...feedItems, ...response.data]);
})
.catch(error => {
// ...handle/report the fact an error occurred...
});
}, []);
实例:
const { useState, useEffect } = React;
// Mock `AsyncStorage`
const AsyncStorage = {
getItem() {
return Promise.resolve("some token");
},
};
// Mock `axios`
const axios = {
get() {
return new Promise(resolve => {
setTimeout(() => {
resolve({data: [
{id: 1, text: "Item 1"},
{id: 2, text: "Item 2"},
{id: 3, text: "Item 3"},
{id: 4, text: "Item 4"},
]});
}, 800);
});
},
};
const Example = () => {
const [feedItems, setFeedItems] = useState([]);
useEffect(() => {
AsyncStorage.getItem("accessToken").
then(accessToken => axios.get(
"http://repor****-env-1.eba-nj*******/feed",
{
headers: {
Authorization: "Bearer " + accessToken,
},
}))
.then((response) => {
setFeedItems(response.data);
})
.catch(error => {
// ...handle/report the fact an error occurred...
});
}, []);
return <div>
<div>Item count: {feedItems.length}</div>
{feedItems.map(({id, text}) => <div key={id}>{text}</div>)}
</div>;
};
ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
好吧,您的代码有几个问题:
useEffect
不应该使用async
函数。您应该在里面创建一个异步函数并在那里调用它- 您正在使用
await
和then
。应该坚持一个 - 实际上,您在这里添加了一个元素
setFeedItems(...feedItems, response.data[i]);
,而不是一个数组
尝试使用此setFeedItems([...feedItems, response.data[i]]);
这将修复错误,但不会解决您的问题,因为您正在使用旧的feedItem
。
为什么不一次用response.data
中的所有项更新状态?代替
for (let i = 0; i < response.data.length; i++) {
setFeedItems(...feedItems, response.data[i]);
}
只需:
if (response.data.length) setFeedItems(prevState => [...prevState, ...response.data])