当我尝试使用 useEffect 从 firebase 获取信息到 nextjs 时出现无限循环

Infinity loop when I try to get information from firebase into nextjs using useEffect

我正在使用 NextJS 为项目创建视频部分。我在 firebase 存储.

中有这些视频

我创建了一个动态路由,它从存储桶的特定引用启动所有视频。例如,我的存储桶是 somebucket 并且有一个名为 training 的文件夹,其中包含类别(category-1、category-2、category-3)。每个类别将是一个动态路由,例如 localhost:3000/training/category-1。到这里,一切都很好。

动态路由文件[id].js

// ReactJS
import { useState, useEffect } from "react";

// NextJS
import { useRouter } from "next/router";

// Hooks
import { withProtected } from "../../../hook/route";

// Components
import DashboardLayout from "../../../layouts/Dashboard";

// Firebase
import { getMetadata, listAll, ref } from "firebase/storage";
import { storage } from "../../../config/firebase";

// Utils
import capitalize from "../../../utils/capitalize";
import { PlayIcon } from "@heroicons/react/outline";

function Video() {
  // States
  const [videos, setVideos] = useState([]);

  // Routing
  const router = useRouter();
  const { id } = router.query;

  // Reference
  const reference = ref(storage, `training/${id}`);

  useEffect(() => {
    function exec() {
      listAll(reference).then((snapshot) => {
        const videos = [];
        snapshot.items.forEach((video) => {
          videos.push(video);
        });

        setVideos(videos);
      });
    }

    exec();
  }, [reference, videos]);

  return (
    <DashboardLayout>
      <h2>{capitalize(reference.name)}</h2>
      <section>
        <video controls controlsList="nodownload">
          <source
            src="https://example.com"
            type="video/mp4"
          />
        </video>
        <ul role="list" className="divide-y divide-gray-200 my-4">
          {videos.map((video) => (
            <li key={video.name} className="py-4 flex">
              <div className="ml-3 flex flex-row justify-start items-center space-x-3">
                <PlayIcon className="w-6 h-6 text-gray-600" />
                <p className="text-sm font-medium text-gray-900">
                  {video.name}
                </p>
              </div>
            </li>
          ))}
        </ul>
      </section>
    </DashboardLayout>
  );
}

export default withProtected(Video);

我根据路线进行动态参考:

// Reference
const reference = ref(storage, `training/${id}`);

如前所述,此引用将使用 listAll 方法列出:

useEffect(() => {
    function exec() {
      listAll(reference).then((snapshot) => {
        const videos = [];
        snapshot.items.forEach((video) => {
          videos.push(video);
        });

        setVideos(videos);
      });
    }

exec();
}, [reference]);

我将元素作为数组推送到状态,然后状态将由组件迭代。显然工作罚款,但我有一个无限循环:

有人知道为什么会这样吗?

我不确定问题出在哪里,但在 useEffects 数组依赖项列表中只包含 id 参数不是更好吗。

我认为这会更好,因为您只有不同的视频,具体取决于路线,所以只有当路线改变时,useEffect 才必须重新运行。

你的问题可能出在这个

useEffect(() => {
    function exec() {
      listAll(reference).then((snapshot) => {
        const videos = [];
        snapshot.items.forEach((video) => {
          videos.push(video);
        });

        setVideos(videos); //update `videos` again --> call `useEffect` again due to `videos` update
      });
    }

    exec();
  }, [reference, videos]); //`videos` dependency 

您应该在 useEffect 依赖项列表中删除 videos

useEffect(() => {
    function exec() {
      listAll(reference).then((snapshot) => {
        const videos = [];
        snapshot.items.forEach((video) => {
          videos.push(video);
        });

        setVideos(videos);
      });
    }

    exec();
  }, [reference]);