在ReactJS中的useEffect中使用传播运算符

时间:2020-01-26 17:17:29

标签: reactjs react-hooks use-effect

我必须通过API呈现200位名人的名单。 我已经绘制了一次20位名人的名单,因此我将如下所示的useEffect更新为200位,而不是20位

但是,当我不使用传播运算符时,什么也不会呈现,它仅在使用它们时呈现,并且我不明白为什么我必须使用2个我的celebrities变量和res.data.results与传播运算符以使其起作用

有人可以向我解释吗?

NB: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 个答案:

答案 0 :(得分:1)

如果我明白您的意思,您将无法理解传播操作员的用法。 通过这样做

setCelebrities(celebs => [ ...celebs, ...res.data.results ])

您在说:

  • 带我以前的名人(名人)
  • 并返回一个新数组[],其中包含我之前的名人对象(... celebs)和我的新名人对象(..res.data.results),此数组将设置为celebrities变量的新值。

如果不这样做,最终将得到一个包含两个数组的数组。

答案 1 :(得分:1)

首先,您要同时启动多个异步调用。我不知道这是否是您要执行的操作,但要考虑到它们可以按照您调用它们的不同顺序进行解析(即,对第3页的请求可以在对第1页的请求之前完成)。

现在,使用传播算子问题。您正在通过回调形式调用 mapper.getFactory().configure(JsonWriteFeature.ESCAPE_NON_ASCII.mappedFeature(), true); 来更新状态。您的状态setCelebrities是一个数组,因此您想使用一个数组进行更新。

celebrities

使用此代码,您将创建一个新的数组,其中的第一部分是您已经拥有的元素(这就是为什么您需要使用散布运算符,因此对您拥有的元素进行了结构化)以及从API获得的结果(这也是一个数组,因此您需要进行分解)。如果不对它们进行分解,那么最终将得到一个数组数组。

如果您不想使用传播运算符,则可以使用concat方法:

setCelebrities(celebs => [
    ...celebs,
    ...res.data.results
])

答案 2 :(得分:1)

由于您要发出10个不同的请求,因此需要合并而不是将当前结果替换为先前的请求,因此需要使用散布或合并。

但是,您有两个问题:

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