Encountering an endless loop while attempting to retrieve data from Firebase in Next.js through the use of useEffect

Currently, I am in the process of setting up a video section for a project using NextJS. The videos are stored in firebase storage.

I have implemented a dynamic route that retrieves all videos from a specific reference within the bucket. For instance, if my bucket is named somebucket and it contains a folder called training with categories (category-1, category-2, category-3), each category will serve as a dynamic route like localhost:3000/training/category-1. So far, everything is running smoothly.

The file responsible for the dynamic route is named [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);

To create a dynamic reference based on the route, I utilize the following code:

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

This reference is then listed using the listAll method mentioned earlier:

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

        setVideos(videos);
      });
    }

exec();
}, [reference]);

After pushing the elements to a state as an array, the state is iterated by a component. Everything seems to be functioning properly, but I encounter an infinite loop:

https://i.stack.imgur.com/tApLj.png

If anyone has insights into why this issue is occurring, please share your thoughts!

Answer №1

It's unclear what the problem is, but perhaps it would be more optimal to include only the id parameter in the useEffects array dependency list.

This approach may be more efficient since the videos are dependent on the route, so the useEffect will only need to re-run when the route changes.

Answer №2

It seems like the issue might be originating from this section of your code

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

        setVideos(videos); //updating `videos` triggers another call to `useEffect` due to its dependency
      });
    }

    execute();
  }, [items, videos]); //dependency on `videos` 

To resolve this, consider removing videos from the dependencies list in your useEffect

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

        setVideos(videos);
      });
    }

    execute();
  }, [items]);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The nuSelectable plugin enhances the functionality of jQuery

I am currently experimenting with the jQuery nuSelectable plugin in order to enable users to select multiple items simultaneously. Unfortunately, I am encountering difficulties in making the selection work as intended. You can find the plugin here. After ...

Using an AJAX function to retrieve data from two different server-side scripts and populate two separate HTML elements on the page

My goal in this coding situation is to change values in multiple DOM targets. The example from Tizag shows the DOM being altered within the onreadystatechange function, like this: if(ajaxRequest.readyState == 4){ document.myForm.time.value = ajaxRequ ...

Contrast between sourcing a file from the current directory versus from the node_modules folder

Why does the typescript compiler accept importing from a JS file in the local directory but raises an error when importing from node_modules? Code: import { t2 } from "./t1.js" t2.hello(); import { mat4 } from "./node_modules/gl-matrix/esm ...

Decide whether to fulfill or deny a Promise at a later time in

When working on an Angular2/TypeScript project, a dialog is shown and the system returns a Promise object to the caller. This Promise will be resolved after the user closes the dialog. The interface of the Promise class does not include methods like resol ...

How can you deactivate all form elements in HTML except for the Submit button?

Is there a method available to automatically deactivate all form elements except the submit button as soon as the form loads? This would entail pre-loading data from the backend onto a JSP page while restricting user access for editing. Users will only be ...

Can you please explain why I am unable to remove the item in my code using Node.js and Express?

Currently, I am in the process of learning NodeJS and working on an application that involves adding Bicicleta objects. However, I have encountered an issue where I am unable to delete these objects successfully. Even though the POST request for deletion r ...

Utilizing TypeScript generics to accurately extract type information from state during reduction

In the context of a state reducer presented as follows: const anObject = { fruit: 'Apple', today: new Date(), } function reducer(state, stateReducer) { return stateReducer(state); } const fruit = reducer(anObject, state => state.fruit ...

Tips for ensuring the HTML checkbox element is fully loaded before programmatically selecting it

When a user accesses the page, I want certain checkboxes to be automatically checked. To achieve this, I am storing the IDs of the HTML checkbox elements in a service. Upon entering the page, the service is utilized to retrieve an array containing these ID ...

How can I effectively develop a versatile user interface for a website using Ruby on Rails that is compatible with all

Currently, I am in the midst of developing a web application using Ruby on Rails. Occasionally, I encounter challenges with cross-browser compatibility when it comes to CSS and Javascript. Are there any strategies you recommend to reduce these issues dur ...

Attempting to create an array using jQuery's :checked selector

In my table structure below, I have multiple rows with various data: <tr class="row"> <td class="row-checkbox-delete-row"> <input tabindex="-1" class="checkbox-delete-row" type="checkbox" /> </td> <td class="r ...

In React, CSS @media queries are specifically designed to function only within the Device Mode of Developer Tools

As indicated by the title, I have designed a responsive web app using the React framework along with various @media queries. When I resize the page in Developer Tools' Device Mode, the queries work perfectly fine and everything functions as expected. ...

Having trouble getting Node.js to run Express.js and React.js simultaneously

My tech stack consists of reactjs for the frontend and expressjs for the backend API. I experimented with the following setup: { "name": "carweb", "version": "0.1.0", "private": true, "dependencies": { // list of dependencies }, "scripts ...

A guide on handling POST response body parsing in NodeJS

const express = require("express"); const bodyParser = require("body-parser"); const app = express(); app.use(bodyParser.urlencoded({extended: true})); app.get("/", function(req, res){ res.sendFile(__dirname + "/index.html"); }); app.post("/", function(r ...

Begin your meteor project with a remote MongoDB server on a Windows operating system

Currently tackling a project that requires me to integrate my meteor project with a remote MongoDB server on Windows. I successfully set the environment variable (MONGO_URL="DB LINK") from OSX using terminal commands, but I'm encountering difficulties ...

Leveraging PHP for populating JavaScript variables

I am currently working on populating a Drop-Down menu from a csv file stored on a network share. So far, I have successfully managed to populate the options when the file is in the wwwroot folder. However, I am now encountering an issue with referencing a ...

When working with esbuild in AWS Amplify, an error occurs with the invalid build flag -rw-r--r

I've been working on hosting a Next.js project in AWS Amplify, but I encountered an issue due to the size of my app exceeding the Amplify limit. To address this, I had to utilize the following command to minimize the size of my app during the build pr ...

Leveraging multiple routes for a single component in Angular 6

Creating a component named Dashboard for admin requires passing the username in the route to find user information. This is the routing setup: {path:'dashboard/:username',component:DashboardComponent,children:[ {path:'role',component: ...

Can Highchart dynamically adjust color choices based on the quantity of data points available?

I am trying to figure out how to import a specific color palette into my column graph. I want to use different color palettes based on the number of data points in my graph - for 3 or fewer points, I want to use the top row colors, for 4 points I want to u ...

Best practices for storing non-reactive and static data in a Vue application

Welcome to the community! I'm excited to ask my first question here on StackOverflow. I am currently working with vue.js-v2 and webpack. My goal is to ensure that data remains immutable for child components, which are loaded through the vue-router. T ...

When I try to upload an image onto my website, the layout of my text gets disrupted

There seems to be quite a gap between the welcoming message and the main body text. Significant spacing noticed between Title and body ...