Javascript 将音频文件上载到Firebase云数据库,然后从数据库重新将其发送到React js+;无休止的循环问题

Javascript 将音频文件上载到Firebase云数据库,然后从数据库重新将其发送到React js+;无休止的循环问题,javascript,reactjs,firebase,google-cloud-firestore,Javascript,Reactjs,Firebase,Google Cloud Firestore,我已经面临这个问题很长一段时间了,它真的很艰难,我需要帮助。提前谢谢 以下代码应该是一个表单,可以在firestore云数据库集合中轻松添加新文档: import React, {useState} from 'react'; import db from '../index'; const AddSongs = () => { const [song, setSong] = useState(''); const [artist, setArtist] = useSta

我已经面临这个问题很长一段时间了,它真的很艰难,我需要帮助。提前谢谢

以下代码应该是一个表单,可以在firestore云数据库集合中轻松添加新文档:

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;
import React,{useState}来自“React”;
从“../index”导入数据库;
const AddSongs=()=>{
const[song,setSong]=使用状态(“”);
const[artist,setArtist]=useState(“”);
const[src,setSrc]=useState(“”);
提交常数=(e)=>{
e、 预防默认值();
让songBase=db.collection('songs');
let data={song,artist,src}
宋基
.add(数据)
}
报税表(
添加你的曲目
setSong(e.target.value)}/>
setArtist(e.target.value)}/>
setSrc(e.target.value)}/>
);
}
导出默认歌曲;
然后,这些文档作为普通文档成功添加到云数据库中,其属性/字段为song、Artister和src。 这是另一段代码,它将获取集合中的当前数据并将其呈现给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;
import React,{useState}来自“React”;
从“../index”导入数据库;
const SongList=()=>{
const[list,setList]=useState([]
让songbase=db.collection('歌曲')
songbase.onSnapshot(快照=>{
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=>{
返回(
{songItem.song}
{songItem.artist}
)
})):(没有!)
报税表(
{renderedList}
);
}
导出默认歌曲列表;
然后,这里发生的事情是,songItem在一个空的jsx div中呈现,其中包含一个空的音频标记,并不断地重复自身并向下滚动..!+数据库中的src字段应该呈现在audio标记中,它只是一个字符串,而不是实际文件的引用

我只需要知道在这种情况下,如何将任何类型的文件添加到firebase存储中,然后在数据库中引用这些文件,然后在普通的无重复div中呈现这些文件


非常感谢。

这里的问题是,每次向列表中添加新元素时,您都在更新状态

正确代码:

import React, { useState, useEffect } from 'react';
import db from '../index';

const SongList = () => {
  const [list, setList] = useState([]);

  useEffect(() => {
    const songbase = db.collection('songs');

    songbase.onSnapshot(snapshot => {
      const songList = [];

      snapshot.docs.forEach(doc => {
        const newSong = {
          song: doc.song,
          artist: doc.artist,
          src: doc.src,
          id: Math.random(0, 1)
        };

        songList.push(newSong);
      });

      setList(songList);
    });
  }, []);

  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;
import React,{useState,useffect}来自“React”;
从“../index”导入数据库;
const SongList=()=>{
const[list,setList]=useState([]);
useffect(()=>{
const songbase=db.collection(“歌曲”);
songbase.onSnapshot(快照=>{
const songList=[];
snapshot.docs.forEach(doc=>{
康斯特·纽松={
宋:宋博士,
艺术家:艺术家博士,
src:doc.src,
id:Math.random(0,1)
};
歌曲列表。推送(新闻歌曲);
});
setList(歌曲列表);
});
}, []);
const renderedList=list.length(
list.map(songItem=>{
返回(
{songItem.song}
{songItem.artist}
);
})
) : (
不!
);
返回{renderedList};
};
导出默认歌曲列表;
需要注意的是:不需要在新数组中分散列表,因为它将始终为[],列表的默认状态设置为[]

我们使用无依赖项的useEffect钩子(第二个参数为空数组),这将在组件第一次呈现时在钩子内执行代码,随后呈现时不会重新运行代码。这将防止出现无限循环


如果你有任何疑问,请告诉我

更新每个渲染的状态,将新元素添加到数组中。当然,这会导致无休止的循环。您需要利用这些资源来获取数据。不要在forEach中调用setList,而是这样调用:
setList(snapshot.docs.map(doc=>({/*…*/}))
Brilliant,非常感谢,它工作了,我理解了。如果您还知道如何将真实文件上传到云存储,然后在正在渲染的数据库文档字段中引用它们,即song、Artister和src,那就太好了,因为目前src只是我计算机中歌曲伪造路径的字符串,我想成为一个真正的文件,以便音频可以在上传后播放。我还尝试使用firebase文档中的几个storageRef函数,但都不起作用,或者我不知道在本例中如何使用它们。这有点挑战性。我在过去的工作项目中做过这个。您应该使用云函数,在react中,您将使用表单数据将文件上载到服务器。(您将把文件上传到云存储桶,然后您可以使用指向该数据的链接修改文档!)。这里有一些链接:。在那里,他制作了一个自定义端点,将数据上传到存储器。另外,可以将我的答案标记为正确答案吗?我会很感激的!!