我必须从API渲染200位名人的列表。 我已经渲染了一次 20 位名人的列表,所以我更新了如下所示的 useEffect,以获得 200 而不是 20
但是,当我不使用 spread 运算符时,什么都不会呈现,它只会在我使用它们时才呈现,我不明白为什么我必须使用 2 个名人变量的副本和带有传播运算符的 res.data.results 才能使其工作
有人可以向我解释一下吗?
注意:res.data.results是一个对象数组,我调用它来显示名人列表以及与之关联的所有属性(名称,图片,著名电影等(。 谢谢!
const Celebrities = () => {
const [celebrities, setCelebrities] = useState([])
const [selectedCelebId, setSelectedCelebId] = useState(null)
useEffect(() => {
for (let page = 1; page <= 10; page++) {
axios.get(`https://api.themoviedb.org/3/person/popular?page=${page}&api_key=MY_API_KEY`)
.then(res => {
setCelebrities(celebs => [
...celebs,
...res.data.results
])
})
.catch(err => console.log(err))
}
}, [])
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
首先,您同时启动多个异步调用。我不知道这是否是您想要做的,但考虑到它们可以以您调用它们的不同顺序解决(即对第 3 页的请求可以在对第 1 页的请求之前完成(。
现在,与点差运算符问题。您通过使用回调表单调用setCelebrities
来更新状态。您的状态celebrities
是一个数组,因此您希望使用数组进行更新。
setCelebrities(celebs => [
...celebs,
...res.data.results
])
使用此代码,您将创建一个新数组,其中第一部分是您已有的元素(这就是为什么您需要使用 spread 运算符,因此您拥有的元素被解构(和您从 API 获得的结果(这也是一个数组,因此您需要解构(。如果你不去破坏它们,你最终会得到一个数组数组。
如果不想使用 spread 运算符,可以使用concat
方法:
setCelebrities(celebs => celebs.concat(res.data.results));
如果我明白你说的话,你就无法理解点差运算符的用法。 通过这样做
setCelebrities(celebs => [ ...celebs, ...res.data.results ])
你是说:
- 拿我以前的名人(名人(
- 并返回一个新的数组 [],其中包含我以前的名人对象(...名人(和我的新名人对象(.res.data.results(,此数组将被设置为名人变量的新值。
如果你不这样做,你最终会得到一个包含两个数组的数组。
由于您发出了 10 个不同的请求,因此您需要组合而不是将当前结果替换为之前的结果,因此使用 spread 或 concat。
但是,您有 2 个问题:
- 您正在多次设置状态 (
setCelebrities
(。尽管其中一些调用将被批处理,但其他调用可能会导致不必要的部分呈现。 - 由于您进行了 10 个并行调用,其中一些可能会按顺序完成,这将导致名人列表顺序不正常。
我建议将承诺收集在一个数组中,然后使用Promise.all()
等待所有请求解析,然后获取结果数组,用Array.flat()
将其扁平化,并设置状态。
示例(未测试(:
useEffect(() => {
const promises = []
for (let page = 1; page <= 10; page++) {
const promise = axios.get(`https://api.themoviedb.org/3/person/popular?page=${page}&api_key=MY_API_KEY`)
.then(res => res.data.results) // create a promise that will hold the results
promises.push(promise) // push the promise to the array of promises
}
Promise.all(promises) // wait for promises to resolve, and get an array of results
.then(results => setCelebrities(results.flat())) // flat the array and set the state
}, [])