Uploading audio files to Firebase Cloud Database and then redering it from the Database to React Js + Endless loop issue

Hi guys, I’ve been facing this issue for quite a while now. I’m still a beginner and this is my first project, and this part is a bit challenging, I need help. Thanks in advance.

The following code should be a form that adds new documents easily inside the firestore cloud Data Base collection:


import React, {useState} from 'react';

import db from '../index';

const AddSongs = () => {

    const [song, setSong] = useState('');

    const [artist, setArtist] = useState('');

    const [src, setSrc] = useState('');

    const inSubmit = (e) =>{

        e.preventDefault();

        let songBase = db.collection('songs');

        let data = {song, artist, src}

        songBase

            .add(data)

    }

    return ( 

        <div>

            <form onSubmit={inSubmit}>

                <label>

                    Add Your Track

                </label>

                <input type="text" placeholder="Name of the track" value={song} onChange={e => 

                 setSong(e.target.value)} />

                <input type="text" placeholder="Name of the artist" value={artist} onChange={e => 

                 setArtist(e.target.value)} />

                <input type="file" value={src} onChange={e => setSrc(e.target.value)} />

                <div>

                    <input type="submit" value="add it" />

                </div>

            </form>

        </div>

    );

}

export default AddSongs;

And then, the docs are added to the cloud Database successfully as normal docs with properties/fields which are song, artist and src.
And this is another code which should then take the current data inside the collection and renders it to a jsx div.

import React, {useState} from 'react';

import db from '../index';

const SongList = () => {

    const [list, setList] = useState([])

    let songbase = db.collection('songs')

    songbase.onSnapshot(snapshot =>{

        snapshot.docs.forEach(doc =>{

            setList([...list, {song: doc.song, artist: doc.artist, src: doc.src, id: Math.random(0,1)}])

        })

    })

    const renderedList = list.length ? (list.map(songItem =>{

        return(

            <div key={songItem.id}>

                <span>{songItem.song}</span>

                <audio controls>

                    <source src={songItem.src} type="audio/mpeg" />

                </audio>

                <span>{songItem.artist}</span>

            </div>

        )

    })) : (<h1>nope !</h1>)

    

    return ( 

        <div>

            {renderedList}

        </div>

     );

}

export default SongList;

And then, what happens here is that the songItem gets rendered inside an empty jsx div containing an empty audio tag inside, and repeats itself endlessly and keeps scrolling down… ! + the src field in the db which should be rendered in the audio tag is just a string, not a reference for a real file.

I just need to know in this case, how to add any kind of files to the firebase storage whether audio, image or any other type, and then reference these files in the Database, and then render the files inside a normal none-repeating div.

Help would be much appreciated
Thanks.

Hi, I didn’t use firebase since long time. Maybe I m wrong but you can try these:

  • is there no .on() .once() method to add?
  • do not set the state one by one by looping. Just add all the array in one time
  • do not put components in variable, instead render them directly in code