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。

但是,您有两个问题:

  1. 您多次设置状态 (setCelebrities)。尽管其中一些调用会被批处理,但其他调用可能会导致不必要的部分渲染。
  2. 由于您进行了 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
}, [])