ReactJS useEffect 中展开运算符的使用
Use of spread operator in useEffect in ReactJS
我必须从 API 中呈现 200 位名人的列表。
我已经渲染了一次 20 位名人的列表,所以我像下面那样更新了 useEffect 以获得 200 而不是 20
但是,当我不使用展开运算符时,什么都不会呈现,它只会在我使用它们时呈现,我不明白为什么我必须使用我的名人变量和 [=26= 的 2 个副本] 使用扩展运算符使其工作
有人可以给我解释一下吗?
注意: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>
如果我明白你在说什么,你就不会理解传播运算符的用法。
通过这样做
setCelebrities(celebs => [ ...celebs, ...res.data.results ])
你是说:
- 拿我以前的名人(名人)
- 和 return 一个新数组 [],其中包含我以前的名人对象 (...celebs) 和我的新名人对象 (..res.data.results),这个数组将被设置为名人变量的新值。
如果不这样做,您将得到一个包含两个数组的数组。
首先,您同时发起了多个异步调用。我不知道这是否是您想要做的,但请考虑到它们可以按照您调用它们的不同顺序进行解析(即第 3 页的请求可以在第 1 页的请求之前完成)。
现在,关于传播运算符的问题。您正在通过使用回调形式调用 setCelebrities
来更新状态。你的状态 celebrities
是一个数组,所以你想用数组更新。
setCelebrities(celebs => [
...celebs,
...res.data.results
])
使用这段代码,您将创建一个新数组,其中第一部分是您已经拥有的元素(这就是为什么您需要使用扩展运算符,所以您拥有的元素会被解构)以及您从API(也是数组,需要解构)。如果你不解构它们,你最终会得到一个数组数组。
如果不想使用展开运算符,可以使用concat
方法:
setCelebrities(celebs => celebs.concat(res.data.results));
由于您提出了 10 个不同的请求,因此您需要合并而不是将当前结果替换为之前的结果,因此需要使用 spread 或 concat。
但是,您有两个问题:
- 您多次设置状态 (
setCelebrities
)。尽管其中一些调用会被批处理,但其他调用可能会导致不必要的部分渲染。
- 由于您进行了 10 次并行调用,其中一些可能会乱序完成,这将导致名人列表乱序。
我建议将 promises 收集在一个数组中,然后使用 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
}, [])
我必须从 API 中呈现 200 位名人的列表。 我已经渲染了一次 20 位名人的列表,所以我像下面那样更新了 useEffect 以获得 200 而不是 20
但是,当我不使用展开运算符时,什么都不会呈现,它只会在我使用它们时呈现,我不明白为什么我必须使用我的名人变量和 [=26= 的 2 个副本] 使用扩展运算符使其工作
有人可以给我解释一下吗?
注意: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>
如果我明白你在说什么,你就不会理解传播运算符的用法。 通过这样做
setCelebrities(celebs => [ ...celebs, ...res.data.results ])
你是说:
- 拿我以前的名人(名人)
- 和 return 一个新数组 [],其中包含我以前的名人对象 (...celebs) 和我的新名人对象 (..res.data.results),这个数组将被设置为名人变量的新值。
如果不这样做,您将得到一个包含两个数组的数组。
首先,您同时发起了多个异步调用。我不知道这是否是您想要做的,但请考虑到它们可以按照您调用它们的不同顺序进行解析(即第 3 页的请求可以在第 1 页的请求之前完成)。
现在,关于传播运算符的问题。您正在通过使用回调形式调用 setCelebrities
来更新状态。你的状态 celebrities
是一个数组,所以你想用数组更新。
setCelebrities(celebs => [
...celebs,
...res.data.results
])
使用这段代码,您将创建一个新数组,其中第一部分是您已经拥有的元素(这就是为什么您需要使用扩展运算符,所以您拥有的元素会被解构)以及您从API(也是数组,需要解构)。如果你不解构它们,你最终会得到一个数组数组。
如果不想使用展开运算符,可以使用concat
方法:
setCelebrities(celebs => celebs.concat(res.data.results));
由于您提出了 10 个不同的请求,因此您需要合并而不是将当前结果替换为之前的结果,因此需要使用 spread 或 concat。
但是,您有两个问题:
- 您多次设置状态 (
setCelebrities
)。尽管其中一些调用会被批处理,但其他调用可能会导致不必要的部分渲染。 - 由于您进行了 10 次并行调用,其中一些可能会乱序完成,这将导致名人列表乱序。
我建议将 promises 收集在一个数组中,然后使用 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
}, [])