仅在状态更改时才重新渲染反应组件

时间:2020-05-01 20:36:45

标签: reactjs

hi是Firebase的新手,我想了解为什么该组件不断重渲染。 基本上我想要做的就是获取数据并显示它,并继续监听更改并更新数据,而无需重新加载页面

import React, { useState, useEffect } from 'react';
import firebase from '../util/firebase';

export default function Items() {
  const [items, setItems] = useState();
  useEffect(() => {
    let data = [];
    firebase
      .firestore()
      .collection('items')
      .onSnapshot((snapshot) => {
        let changes = snapshot.docChanges();
        console.log(changes);
        changes.forEach((change) => {
          data.push(change.doc.data());
        });
        console.log(data);
      });
    setItems(data);
  }, [items]);
  return <div>{items && items.map((item) => <h1>{item.text}</h1>)}</div>;
}

1 个答案:

答案 0 :(得分:1)

useEffect在其中一个依赖项发生更改时重新运行传递给它的函数。

如果我们分析当前的useEffect函数,您会看到它使用itemssetItems设置了一个状态,这将导致重新渲染。但是依赖项还包含items

组件安装-> useEffect->设置项目-> useEffect检测到项目更改,重新运行->再次设置项目,然后继续。

由于您实际上并未在items中使用useEffect,因此可以安全地从依赖项数组中删除它。

这里的另一个危险是useSnapshot函数是异步的,因此当编译器进入setItems时,它将尚未运行useSnapshot,因此数据将为空。要解决此问题,您可以在内部移动setItems函数:

const [items, setItems] = useState();
useEffect(() => {
  let data = [];
  firebase
    .firestore()
    .collection("items")
    .onSnapshot((snapshot) => {
      let changes = snapshot.docChanges();
      console.log(changes);
      changes.forEach((change) => {
        data.push(change.doc.data());
      });
// spreading the data here did solve my problem
      setItems([...data]);
    });
}, []);