useEffect 多次渲染,即使数据没有变化

useEffect rendering multiple times even when data is not changing

如果依赖项数组为空,此 useEffect 将渲染一次,但如果我将 folderRef 放入依赖项数组,则会渲染多次。我只想在添加或删除某个文件夹时渲染组件。请帮忙

  import React, { useState, useEffect , useRef } from "react";
import { db } from "../firebase";
import { collection, getDocs } from "firebase/firestore";
import FolderData from "./FolderData";

function ShowFolder(props) {
  const [folders, setFolders] = useState([]);
  const folderRef = useRef(collection(db, "folders"));

  useEffect(() => {
    const getData = async () => {
      const data = await getDocs(folderRef.current);
      const folderData = data.docs.map((doc) => {
        return { id: doc.id, data: doc.data() };
      });
      console.log(folderData);
      setFolders(folderData);
    };
    getData();
  }, [folderRef]);

  return (
    <div className="container md:px-4 mx-auto py-10">
      <div className="md:grid lg:grid-cols-6 md:grid-cols-3 mlg:grid-cols-3 md:gap-10 space-y-6 md:space-y-0 px-1 md:px-0 mx-auto">
        {folders.map((folder) => {
          return (
            <div key={folder.id}>
              {folder.data.userId === props.userId && (
                <div>
                  <FolderData key={folder.id} folder={folder} />
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

export default ShowFolder;

我觉得最有可能你的useState函数是这样的

const[folderRef , setFolders]=useState(Your Initial Value);

如果是这种情况,那么你什么时候执行

useEffect(() => {
setFolder(Setting Anything Here)

....


},[folderRef])

React 会开始无限循环,因为每次您使用 setFolder 时,FolderRef 都会更新,并且 useEffect 会再次被强制 运行,并且不会停止。

使用类似

的东西
const[folderRef , setFolders]=useState(Your Initial Value);
const[isLoading, setIsLoading]=useState(true);


useEffect(() => {
setFolder(Setting Anything Here)
setIsLoading(false)
....


},[])

...


return (
{ isLoading ? "Run the code you wanna run " : null  }
)

您重新声明 folderRef 每个渲染周期,因此如果您将其包含在 useEffect 挂钩的依赖项数组中,它将触发渲染循环。

如果您没有在组件中的其他任何地方引用 folderRef 然后将其移动 useEffect 挂钩回调中以将其作为外部删除依赖性。

const [folders, setFolders] = useState([]);

useEffect(() => {
  const folderRef = collection(db, "folders");

  const getData = async () => {
    const data = await getDocs(folderRef);
    const folderData = data.docs.map((doc) => {
      return { id: doc.id, data: doc.data() };
    });
    console.log(folderData);
    setFolders(folderData);
  };

  getData();
}, []);

或者将其存储在 React ref 中,以便可以安全地引用它作为稳定的引用。

const [folders, setFolders] = useState([]);
const folderRef = useRef(collection(db, "folders"));

useEffect(() => {
  const getData = async () => {
    const data = await getDocs(folderRef.current);
    const folderData = data.docs.map((doc) => {
      return { id: doc.id, data: doc.data() };
    });
    console.log(folderData);
    setFolders(folderData);
  };

  getData();
}, [folderRef]);

更新

我了解到您正在更新应用中其他地方的 folders 集合,并希望此组件“侦听”这些更改。为此,您可以实现一个 onSnapshot 侦听器。

它可能类似于以下内容:

const [folders, setFolders] = useState([]);

useEffect(() => {
  const unsubscribe = onSnapshot(
    collection(db, "folders"),
    (snapshot) => {
      const folderData = [];
      snapshot.forEach((doc) => {
        folderData.push({
          id: doc.id,
          data: doc.data(),
        });
      });
      setFolders(folderData);
    },
  );

  // Return cleanup function to stop listening to changes
  // on component unmount
  return unsubscribe;
}, []);